Implement Intel get/set shutdown policy IPMI OEM commands
Tested By:
ipmitool raw 0x30 0x60 1
ipmitool raw 0x30 0x62
Change-Id: I8ca7429b569a465420c9b878fe29f8617c8ef76c
Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index e988d03..4270330 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -24,6 +24,8 @@
cmdSetSystemGUID = 0x41,
cmdSetPowerRestoreDelay = 0x54,
cmdGetPowerRestoreDelay = 0x55,
+ cmdSetShutdownPolicy = 0x60,
+ cmdGetShutdownPolicy = 0x62,
cmdGetChassisIdentifier = 0x92,
cmdGetProcessorErrConfig = 0x9A,
cmdSetProcessorErrConfig = 0x9B,
@@ -89,6 +91,21 @@
static constexpr const char* processorErrConfigIntf =
"xyz.openbmc_project.Control.Processor.ErrConfig";
+static constexpr const char* postCodesObjPath =
+ "/xyz/openbmc_project/State/Boot/PostCode";
+static constexpr const char* postCodesIntf =
+ "xyz.openbmc_project.State.Boot.PostCode";
+
+static constexpr const uint8_t noShutdownOnOCOT = 0;
+static constexpr const uint8_t shutdownOnOCOT = 1;
+static constexpr const uint8_t noShutdownPolicySupported = 0;
+static constexpr const uint8_t shutdownPolicySupported = 1;
+static constexpr const char* oemShutdownPolicyIntf =
+ "xyz.openbmc_project.Control.ShutdownPolicy";
+static constexpr const char* oemShutdownPolicyObjPath =
+ "/xyz/openbmc_project/control/shutdown_policy_config";
+static constexpr const char* oemShutdownPolicyObjPathProp = "Policy";
+
enum class IPMINetfnIntelOEMAppCmd
{
mdrStatus = 0x20,
@@ -209,4 +226,10 @@
// 01b: Enabled
// 11b: Not Present
};
+
+struct GetOEMShutdownPolicyRes
+{
+ uint8_t policy;
+ uint8_t policySupport;
+};
#pragma pack(pop)
\ No newline at end of file
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 781f6ba..c807255 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -407,6 +407,90 @@
return IPMI_CC_OK;
}
+ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+ ipmi_data_len_t dataLen,
+ ipmi_context_t context)
+{
+ GetOEMShutdownPolicyRes* resp =
+ reinterpret_cast<GetOEMShutdownPolicyRes*>(response);
+
+ if (*dataLen != 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oem_set_shutdown_policy: invalid input len!");
+ *dataLen = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ *dataLen = 0;
+
+ try
+ {
+ std::string service =
+ getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
+ Value variant = getDbusProperty(dbus, service, oemShutdownPolicyObjPath,
+ oemShutdownPolicyIntf,
+ oemShutdownPolicyObjPathProp);
+ resp->policy = sdbusplus::message::variant_ns::get<uint8_t>(variant);
+ // TODO needs to check if it is multi-node products,
+ // policy is only supported on node 3/4
+ resp->policySupport = shutdownPolicySupported;
+ }
+ catch (sdbusplus::exception_t& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ *dataLen = sizeof(GetOEMShutdownPolicyRes);
+ return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request,
+ ipmi_response_t response,
+ ipmi_data_len_t dataLen,
+ ipmi_context_t context)
+{
+ uint8_t* req = reinterpret_cast<uint8_t*>(request);
+
+ // TODO needs to check if it is multi-node products,
+ // policy is only supported on node 3/4
+ if (*dataLen != 1)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oem_set_shutdown_policy: invalid input len!");
+ *dataLen = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ *dataLen = 0;
+ if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oem_set_shutdown_policy: invalid input!");
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ try
+ {
+ std::string service =
+ getService(dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
+ setDbusProperty(dbus, service, oemShutdownPolicyObjPath,
+ oemShutdownPolicyIntf, oemShutdownPolicyObjPathProp,
+ *req);
+ }
+ catch (sdbusplus::exception_t& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ return IPMI_CC_OK;
+}
+
static void registerOEMFunctions(void)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -461,6 +545,14 @@
static_cast<ipmi_cmd_t>(
IPMINetfnIntelOEMGeneralCmd::cmdSetProcessorErrConfig),
NULL, ipmiOEMSetProcessorErrConfig, PRIVILEGE_ADMIN);
+ ipmiPrintAndRegister(netfnIntcOEMGeneral,
+ static_cast<ipmi_cmd_t>(
+ IPMINetfnIntelOEMGeneralCmd::cmdSetShutdownPolicy),
+ NULL, ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN);
+ ipmiPrintAndRegister(netfnIntcOEMGeneral,
+ static_cast<ipmi_cmd_t>(
+ IPMINetfnIntelOEMGeneralCmd::cmdGetShutdownPolicy),
+ NULL, ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN);
return;
}