Update Get SM Signal command for front panel buttons
This change updates the Get SM Signal command to use the power
control Button service instead of the GPIO daemon to mask and
read the front panel buttons.
This change also updates the Get SM Signal command to the new API.
Tested:
Tested the Get SM Signal IPMI commands to verify that the front panel
buttons can be masked and read:
power button:
ipmitool raw 0x30 0x14 0 0 0
00
ipmitool raw 0x30 0x14 0 0 1
00
ipmitool raw 0x30 0x14 0 0 0
01
ipmitool raw 0x30 0x14 0 0 2
00
reset button:
ipmitool raw 0x30 0x14 1 0 0
00
ipmitool raw 0x30 0x14 1 0 1
00
ipmitool raw 0x30 0x14 1 0 0
01
ipmitool raw 0x30 0x14 1 0 2
00
nmi button:
ipmitool raw 0x30 0x14 3 0 0
00
ipmitool raw 0x30 0x14 3 0 1
00
ipmitool raw 0x30 0x14 3 0 0
01
ipmitool raw 0x30 0x14 3 0 2
00
Change-Id: Idbb1be30b22d653f8805e1f8addf18a197dc4ee5
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/src/manufacturingcommands.cpp b/src/manufacturingcommands.cpp
index 7bbb970..4993566 100644
--- a/src/manufacturingcommands.cpp
+++ b/src/manufacturingcommands.cpp
@@ -14,7 +14,6 @@
// limitations under the License.
*/
-#include <boost/process/child.hpp>
#include <ipmid/api.hpp>
#include <manufacturingcommands.hpp>
#include <oemcommands.hpp>
@@ -28,12 +27,6 @@
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::seconds(60)); // 1 minute timeout
-static constexpr const char* idButtonPath =
- "/xyz/openbmc_project/Chassis/Buttons/ID0";
-static constexpr const char* idButtonInterface =
- "xyz.openbmc_project.Chassis.Buttons.ID";
-static constexpr const char* idButtonMemberPressed = "Pressed";
-
static constexpr const char* callbackMgrService =
"xyz.openbmc_project.CallbackManager";
static constexpr const char* callbackMgrIntf =
@@ -48,13 +41,24 @@
"org.freedesktop.systemd1.Manager";
const static constexpr char* pidControlService = "phosphor-pid-control.service";
-// TODO: Temporary place to test the working code. Will be moved to
-// gpio daemon
-constexpr const char* passthroughPath = "/usr/bin/set-passthrough.sh";
-void disablePassthrough(bool value)
+int getGpioPathForSmSignal(const SmSignalGet signal, std::string& path)
{
- boost::process::child c(passthroughPath, value ? "0" : "1");
- c.wait();
+ switch (signal)
+ {
+ case SmSignalGet::smPowerButton:
+ path = "/xyz/openbmc_project/chassis/buttons/power";
+ break;
+ case SmSignalGet::smResetButton:
+ path = "/xyz/openbmc_project/chassis/buttons/reset";
+ break;
+ case SmSignalGet::smNMIButton:
+ path = "/xyz/openbmc_project/chassis/buttons/nmi";
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
}
ipmi_ret_t ledStoreAndSet(SmSignalSet signal, std::string setState)
@@ -85,7 +89,7 @@
mtm.revertLedCallback = true;
}
}
- if (mtm.setProperty(ledService.c_str(), ledPath.c_str(), ledIntf, "State",
+ if (mtm.setProperty(ledService, ledPath, ledIntf, "State",
ledStateStr + setState) != 0)
{
return IPMI_CC_UNSPECIFIED_ERROR;
@@ -123,8 +127,8 @@
std::string ledName = ledProp->getName();
std::string ledService = ledServicePrefix + ledName;
std::string ledPath = ledPathPrefix + ledName;
- if (mtm.setProperty(ledService.c_str(), ledPath.c_str(), ledIntf,
- "State", ledProp->getPrevState()) != 0)
+ if (mtm.setProperty(ledService, ledPath, ledIntf, "State",
+ ledProp->getPrevState()) != 0)
{
return IPMI_CC_UNSPECIFIED_ERROR;
}
@@ -135,14 +139,6 @@
void Manufacturing::initData()
{
- gpioPaths[(uint8_t)SmSignalGet::smPowerButton] = "Power_Button";
- gpioPaths[(uint8_t)SmSignalGet::smResetButton] = "Reset_Button";
- gpioPaths[(uint8_t)SmSignalGet::smIdentifyButton] = "ID_Button";
- gpioPaths[(uint8_t)SmSignalGet::smFpLcpEnterButton] = "Lcp_Enter_Button";
- gpioPaths[(uint8_t)SmSignalGet::smFpLcpLeftButton] = "Lcp_Left_Button";
- gpioPaths[(uint8_t)SmSignalGet::smFpLcpRightButton] = "Lcp_Right_Button";
- gpioPaths[(uint8_t)SmSignalGet::smNmiButton] = "Nmi_Button";
-
ledPropertyList.push_back(
LedProperty(SmSignalSet::smPowerFaultLed, "status_amber"));
ledPropertyList.push_back(
@@ -153,14 +149,6 @@
void Manufacturing::revertTimerHandler()
{
- for (const auto& signal : revertSmSignalGetVector)
- {
- mtm.setProperty(gpioService,
- mtm.getGpioPathForSmSignal((uint8_t)signal), gpioIntf,
- "Ignore", false);
- }
- revertSmSignalGetVector.clear();
- disablePassthrough(false);
if (revertFanPWM)
{
revertFanPWM = false;
@@ -180,14 +168,16 @@
initData();
}
-int8_t Manufacturing::getProperty(const char* service, std::string path,
- const char* interface,
- std::string propertyName, ipmi::Value* reply)
+int8_t Manufacturing::getProperty(const std::string& service,
+ const std::string& path,
+ const std::string& interface,
+ const std::string& propertyName,
+ ipmi::Value* reply)
{
try
{
- *reply = ipmi::getDbusProperty(*getSdBus(), service, path.c_str(),
- interface, propertyName);
+ *reply = ipmi::getDbusProperty(*getSdBus(), service, path, interface,
+ propertyName);
}
catch (const sdbusplus::exception::SdBusError& e)
{
@@ -199,13 +189,15 @@
return 0;
}
-int8_t Manufacturing::setProperty(const char* service, std::string path,
- const char* interface,
- std::string propertyName, ipmi::Value value)
+int8_t Manufacturing::setProperty(const std::string& service,
+ const std::string& path,
+ const std::string& interface,
+ const std::string& propertyName,
+ ipmi::Value value)
{
try
{
- ipmi::setDbusProperty(*getSdBus(), service, path.c_str(), interface,
+ ipmi::setDbusProperty(*getSdBus(), service, path, interface,
propertyName, value);
}
catch (const sdbusplus::exception::SdBusError& e)
@@ -238,202 +230,146 @@
return 0;
}
-std::tuple<uint8_t, ipmi_ret_t, uint8_t>
- Manufacturing::proccessSignal(SmSignalGet signal, SmActionGet action)
+ipmi::RspType<uint8_t, // Signal value
+ std::optional<uint16_t> // Fan tach value
+ >
+ appMTMGetSignal(uint8_t signalTypeByte, uint8_t instance,
+ uint8_t actionByte)
{
- int8_t ret = 0;
- uint8_t retCode = 0;
- uint8_t dataLen = 0;
- uint8_t value = 0;
- ipmi::Value reply;
-
- switch (action)
+ if (mtm.getAccessLvl() < MtmLvl::mtmAvailable)
{
- case SmActionGet::sample:
- phosphor::logging::log<phosphor::logging::level::INFO>(
- "case SmActionGet::sample");
- break;
- case SmActionGet::ignore:
- {
- phosphor::logging::log<phosphor::logging::level::INFO>(
- "case SmActionGet::ignore");
- if (std::find(revertSmSignalGetVector.begin(),
- revertSmSignalGetVector.end(),
- signal) == revertSmSignalGetVector.end())
- {
- // Todo: Needs to be replaced with pass-through of particular
- // pin
- disablePassthrough(true);
- ret = mtm.setProperty(
- gpioService, mtm.getGpioPathForSmSignal((uint8_t)signal),
- gpioIntf, "Ignore", true);
- if (ret < 0)
- {
- dataLen = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- }
- revertSmSignalGetVector.push_back(signal);
- revertTimer.start(revertTimeOut);
- }
- }
- break;
- case SmActionGet::revert:
- {
- phosphor::logging::log<phosphor::logging::level::INFO>(
- "case SmActionGet::revert");
- auto iter = std::find(revertSmSignalGetVector.begin(),
- revertSmSignalGetVector.end(), signal);
- if (iter != revertSmSignalGetVector.end())
- {
- ret = mtm.setProperty(
- gpioService, mtm.getGpioPathForSmSignal((uint8_t)signal),
- gpioIntf, "Ignore", false);
- if (ret < 0)
- {
- dataLen = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- }
- revertSmSignalGetVector.erase(iter);
- // Todo: Needs to be replaced with pass-through of particular
- // pin
- disablePassthrough(true);
- if (revertSmSignalGetVector.size() == 0)
- {
- revertTimer.stop();
- }
- }
- }
- break;
+ return ipmi::responseInvalidCommand();
+ }
+ SmSignalGet signalType = static_cast<SmSignalGet>(signalTypeByte);
+ SmActionGet action = static_cast<SmActionGet>(actionByte);
+
+ switch (signalType)
+ {
+ case SmSignalGet::smFanPwmGet:
+ {
+ ipmi::Value reply;
+ std::string fullPath = fanPwmPath + std::to_string(instance);
+ if (mtm.getProperty(fanService, fullPath, fanIntf, "Value",
+ &reply) < 0)
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ double* doubleVal = std::get_if<double>(&reply);
+ if (doubleVal == nullptr)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ uint8_t sensorVal = std::round(*doubleVal);
+ return ipmi::responseSuccess(sensorVal, std::nullopt);
+ }
+ break;
+ case SmSignalGet::smFanTachometerGet:
+
+ {
+ // Full path calculation pattern:
+ // Instance 1 path is
+ // /xyz/openbmc_project/sensors/fan_tach/Fan_1a Instance 2 path
+ // is /xyz/openbmc_project/sensors/fan_tach/Fan_1b Instance 3
+ // path is /xyz/openbmc_project/sensors/fan_tach/Fan_2a
+ // and so on...
+ std::string fullPath = fanTachPathPrefix;
+ std::string fanAb = (instance % 2) == 0 ? "b" : "a";
+ if (0 == instance)
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ else if (0 == instance / 2)
+ {
+ fullPath += std::string("1") + fanAb;
+ }
+ else
+ {
+ fullPath += std::to_string(instance / 2) + fanAb;
+ }
+
+ ipmi::Value reply;
+ if (mtm.getProperty(fanService, fullPath, fanIntf, "Value",
+ &reply) < 0)
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ double* doubleVal = std::get_if<double>(&reply);
+ if (doubleVal == nullptr)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ uint8_t sensorVal = FAN_PRESENT | FAN_SENSOR_PRESENT;
+ std::optional<uint16_t> fanTach = std::round(*doubleVal);
+
+ return ipmi::responseSuccess(sensorVal, fanTach);
+ }
+ break;
+ case SmSignalGet::smResetButton:
+ case SmSignalGet::smPowerButton:
+ case SmSignalGet::smNMIButton:
+ case SmSignalGet::smIdentifyButton:
+ {
+ std::string path;
+ if (getGpioPathForSmSignal(signalType, path) < 0)
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ switch (action)
+ {
+ case SmActionGet::sample:
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "case SmActionGet::sample");
+ break;
+ case SmActionGet::ignore:
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "case SmActionGet::ignore");
+ if (mtm.setProperty(buttonService, path, buttonIntf,
+ "ButtonMasked", true) < 0)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ }
+ break;
+ case SmActionGet::revert:
+ {
+ phosphor::logging::log<phosphor::logging::level::INFO>(
+ "case SmActionGet::revert");
+ if (mtm.setProperty(buttonService, path, buttonIntf,
+ "ButtonMasked", false) < 0)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ }
+ break;
+
+ default:
+ return ipmi::responseInvalidFieldRequest();
+ break;
+ }
+
+ ipmi::Value reply;
+ if (mtm.getProperty(buttonService, path, buttonIntf,
+ "ButtonPressed", &reply) < 0)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ bool* valPtr = std::get_if<bool>(&reply);
+ if (valPtr == nullptr)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ uint8_t sensorVal = *valPtr;
+ return ipmi::responseSuccess(sensorVal, std::nullopt);
+ }
+ break;
default:
- dataLen = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
+ return ipmi::responseInvalidFieldRequest();
break;
}
-
- if (ret == 0) // No error happend, cmd will return with gpio value
- {
- ret = mtm.getProperty(gpioService,
- mtm.getGpioPathForSmSignal((uint8_t)signal),
- gpioIntf, "SampledValue", &reply);
- if (ret < 0)
- {
- dataLen = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- }
- else
- {
- dataLen = 1;
- value = std::get<bool>(reply);
- }
- }
-
- return std::make_tuple(dataLen, retCode, value);
-}
-
-ipmi_ret_t ipmi_app_mtm_get_signal(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
- ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t data_len,
- ipmi_context_t context)
-{
- ipmi_ret_t retCode = IPMI_CC_OK;
- int8_t ret = 0;
- GetSmSignalReq* pReq = NULL;
- GetSmSignalRsp* pRsp = NULL;
-
- pReq = static_cast<GetSmSignalReq*>(request);
- pRsp = static_cast<GetSmSignalRsp*>(response);
-
- ipmi::Value reply;
-
- if ((*data_len == sizeof(*pReq)) &&
- (mtm.getAccessLvl() >= MtmLvl::mtmAvailable))
- {
- switch (pReq->Signal)
- {
- case SmSignalGet::smFanPwmGet:
- {
- std::string fullPath =
- fanPwmPath + std::to_string(pReq->Instance);
- ret = mtm.getProperty(fanService, fullPath, fanIntf, "Value",
- &reply);
- if (ret < 0)
- {
- *data_len = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- break;
- }
- *data_len = 1;
- pRsp->SigVal = std::get<double>(reply);
- }
- break;
- case SmSignalGet::smFanTachometerGet:
- {
- // Full path calculation pattern:
- // Instance 1 path is
- // /xyz/openbmc_project/sensors/fan_tach/Fan_1a Instance 2 path
- // is /xyz/openbmc_project/sensors/fan_tach/Fan_1b Instance 3
- // path is /xyz/openbmc_project/sensors/fan_tach/Fan_2a
- // and so on...
- std::string fullPath = fanTachPathPrefix;
- std::string fanAb = (pReq->Instance % 2) == 0 ? "b" : "a";
- if (0 == pReq->Instance)
- {
- *data_len = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- break;
- }
- else if (0 == pReq->Instance / 2)
- {
- fullPath += std::string("1") + fanAb;
- }
- else
- {
- fullPath += std::to_string(pReq->Instance / 2) + fanAb;
- }
-
- ret = mtm.getProperty(fanService, fullPath, fanIntf, "Value",
- &reply);
- if (ret < 0)
- {
- *data_len = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- break;
- }
-
- uint16_t value = std::get<double>(reply);
- *data_len = sizeof(*pRsp);
-
- pRsp->SigVal = FAN_PRESENT | FAN_SENSOR_PRESENT;
- pRsp->SigVal1 = value & 0x00FF;
- pRsp->SigVal2 = (value >> 8) & 0xFF;
- }
- break;
- case SmSignalGet::smResetButton: // gpio32
- case SmSignalGet::smPowerButton: // gpio34
- case SmSignalGet::smFpLcpEnterButton: // gpio51
- case SmSignalGet::smFpLcpLeftButton: // gpio52
- case SmSignalGet::smFpLcpRightButton: // gpio53
- case SmSignalGet::smNmiButton: // gpio217
- case SmSignalGet::smIdentifyButton: // gpio218
- std::tie(*data_len, retCode, pRsp->SigVal) =
- mtm.proccessSignal(pReq->Signal, pReq->Action);
- *data_len = sizeof(pRsp->SigVal);
- break;
- default:
- *data_len = 0;
- retCode = IPMI_CC_INVALID_FIELD_REQUEST;
- break;
- }
- }
- else
- {
- *data_len = 0;
- retCode = IPMI_CC_REQ_DATA_LEN_INVALID;
- }
-
- return retCode;
}
ipmi_ret_t ipmi_app_mtm_set_signal(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -576,9 +512,9 @@
std::string fanPwmInstancePath =
fanPwmPath + std::to_string(pReq->Instance);
- ret = mtm.setProperty(
- fanService, fanPwmInstancePath.c_str(), fanIntf,
- "Value", static_cast<double>(pwmValue));
+ ret = mtm.setProperty(fanService, fanPwmInstancePath,
+ fanIntf, "Value",
+ static_cast<double>(pwmValue));
if (ret < 0)
{
retCode = IPMI_CC_UNSPECIFIED_ERROR;
@@ -614,10 +550,11 @@
void register_mtm_commands() __attribute__((constructor));
void register_mtm_commands()
{
- ipmi_register_callback(
- netfnIntcOEMGeneral,
- static_cast<ipmi_cmd_t>(IPMINetFnIntelOemGeneralCmds::GetSmSignal),
- NULL, ipmi::ipmi_app_mtm_get_signal, PRIVILEGE_USER);
+ // <Get SM Signal>
+ ipmi::registerHandler(
+ ipmi::prioOemBase, ipmi::netFnOemOne,
+ static_cast<ipmi::Cmd>(IPMINetFnIntelOemGeneralCmds::GetSmSignal),
+ ipmi::Privilege::User, ipmi::appMTMGetSignal);
ipmi_register_callback(
netfnIntcOEMGeneral,