IPMI set CurrentHostState property
Register an IPMI handler to receive the command from BIC
netFn: 0x38 cmd: 0x0C
BIC sends the GPIO value for host power state to BMC
On: 0x1
Off: 0x0
This handler starts the corresponding target to set
"CurrentHostState" property
On: obmc-host-startmin@$slot.target
Off: obmc-host-stop@@$slot.target
Test Case:
Set "RequestedHostTransition" property on phosphor-state-manager
to On/Off/Reboot/ForceWarmReboot and check the host status
Signed-off-by: Bonnie Lo <Bonnie_Lo@wiwynn.com>
Change-Id: I891f38d7e836238fa3ba8287df5a855cf2d9a8d9
diff --git a/include/biccommands.hpp b/include/biccommands.hpp
index e8742d1..8702380 100644
--- a/include/biccommands.hpp
+++ b/include/biccommands.hpp
@@ -4,8 +4,19 @@
CMD_OEM_BIC_INFO = 0x1,
CMD_OEM_GET_BIC_GPIO_STATE = 0x3,
CMD_OEM_SEND_POST_BUFFER_TO_BMC = 0x8,
+ CMD_OEM_SET_HOST_POWER_STATE = 0x0C,
};
const char* dbusObj = "/xyz/openbmc_project/state/boot/raw";
const char* dbusService = "xyz.openbmc_project.State.Boot.Raw";
+
+constexpr auto systemdService = "org.freedesktop.systemd1";
+constexpr auto systemdObjPath = "/org/freedesktop/systemd1";
+constexpr auto systemdInterface = "org.freedesktop.systemd1.Manager";
+
+enum class HostPowerState : uint8_t
+{
+ HOST_POWER_OFF = 0x0,
+ HOST_POWER_ON = 0x1,
+};
diff --git a/src/biccommands.cpp b/src/biccommands.cpp
index 5212452..13907e1 100644
--- a/src/biccommands.cpp
+++ b/src/biccommands.cpp
@@ -155,6 +155,57 @@
return ipmi::responseSuccess(respIana, gpioState);
}
+//----------------------------------------------------------------------
+// ipmiOemSetHostPowerState (CMD_OEM_SET_HOST_POWER_STATE)
+// This Function will handle BIC incomming IPMI request for
+// setting host current state for netfn=0x38 and cmd=0x0C
+// send the response back to the sender.
+//----------------------------------------------------------------------
+
+ipmi::RspType<IanaType> ipmiOemSetHostPowerState(ipmi::Context::ptr ctx,
+ IanaType reqIana,
+ uint8_t status)
+{
+ std::string targetUnit;
+
+ switch (static_cast<HostPowerState>(status))
+ {
+ case HostPowerState::HOST_POWER_ON:
+ targetUnit = "obmc-host-startmin@.target";
+ break;
+ case HostPowerState::HOST_POWER_OFF:
+ targetUnit = "obmc-host-stop@.target";
+ break;
+ default:
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "IPMI ipmiOemHostPowerStatus power status error");
+ return ipmi::responseUnspecifiedError();
+ }
+
+ int mousePos = targetUnit.find('@');
+ targetUnit.insert(mousePos + 1, std::to_string(ctx->hostIdx + 1));
+
+ auto conn = getSdBus();
+ auto method = conn->new_method_call(systemdService, systemdObjPath,
+ systemdInterface, "StartUnit");
+ method.append(targetUnit);
+ method.append("replace");
+
+ try
+ {
+ conn->call_noreply(method);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "IPMI ipmiOemHostPowerStatus Failed in call method",
+ phosphor::logging::entry("ERROR=%s", e.what()));
+ return ipmi::responseUnspecifiedError();
+ }
+
+ return ipmi::responseSuccess(reqIana);
+}
+
[[maybe_unused]] static void registerBICFunctions(void)
{
@@ -172,6 +223,10 @@
ipmi::prioOemBase, ipmi::netFnOemFive,
static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
ipmi::Privilege::User, ipmiOemGetBicGpioState);
+ ipmi::registerHandler(
+ ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
+ static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SET_HOST_POWER_STATE),
+ ipmi::Privilege::User, ipmiOemSetHostPowerState);
return;
}