summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/watchdog.cpp98
-rw-r--r--app/watchdog.hpp18
-rw-r--r--apphandler.cpp7
-rw-r--r--apphandler.h1
-rw-r--r--host-ipmid-whitelist.conf1
5 files changed, 125 insertions, 0 deletions
diff --git a/app/watchdog.cpp b/app/watchdog.cpp
index 84d80b9..7b1d987 100644
--- a/app/watchdog.cpp
+++ b/app/watchdog.cpp
@@ -167,3 +167,101 @@ ipmi_ret_t ipmi_app_watchdog_set(
return IPMI_CC_UNSPECIFIED_ERROR;
}
}
+
+/** @brief Converts a DBUS Watchdog Action to IPMI defined action
+ * @param[in] wd_action The DBUS Watchdog Action
+ * @return The IpmiAction that the wd_action maps to
+ */
+IpmiAction wdActionToIpmiAction(WatchdogService::Action wd_action)
+{
+ switch(wd_action)
+ {
+ case WatchdogService::Action::None:
+ {
+ return IpmiAction::None;
+ }
+ case WatchdogService::Action::HardReset:
+ {
+ return IpmiAction::HardReset;
+ }
+ case WatchdogService::Action::PowerOff:
+ {
+ return IpmiAction::PowerOff;
+ }
+ case WatchdogService::Action::PowerCycle:
+ {
+ return IpmiAction::PowerCycle;
+ }
+ default:
+ {
+ // We have no method via IPMI to signal that the action is unknown
+ // or unmappable in some way.
+ // Just ignore the error and return NONE so the host can reconcile.
+ return IpmiAction::None;
+ }
+ }
+}
+
+struct wd_get_res {
+ uint8_t timer_use;
+ uint8_t timer_action;
+ uint8_t pretimeout;
+ uint8_t expire_flags;
+ uint16_t initial_countdown; // Little Endian (deciseconds)
+ uint16_t present_countdown; // Little Endian (deciseconds)
+} __attribute__ ((packed));
+static_assert(sizeof(wd_get_res) == 8, "wd_get_res has invalid size.");
+static_assert(sizeof(wd_get_res) <= MAX_IPMI_BUFFER,
+ "wd_get_res can't fit in response buffer.");
+
+static constexpr uint8_t wd_dont_log = 0x1 << 7;
+static constexpr uint8_t wd_running = 0x1 << 6;
+
+ipmi_ret_t ipmi_app_watchdog_get(
+ 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)
+{
+ // Assume we will fail and send no data outside the return code
+ *data_len = 0;
+
+ try
+ {
+ WatchdogService wd_service;
+ WatchdogService::Properties wd_prop = wd_service.getProperties();
+
+ // Build and return the response
+ wd_get_res res;
+ res.timer_use = wd_dont_log;
+ res.timer_action = static_cast<uint8_t>(
+ wdActionToIpmiAction(wd_prop.expireAction));
+ if (wd_prop.enabled)
+ {
+ res.timer_use |= wd_running;
+ }
+ // TODO: Do something about having pretimeout support
+ res.pretimeout = 0;
+ res.expire_flags = 0;
+ // Interval and timeRemaining need converted from milli -> deci seconds
+ res.initial_countdown = htole16(wd_prop.interval / 100);
+ res.present_countdown = htole16(wd_prop.timeRemaining / 100);
+
+ memcpy(response, &res, sizeof(res));
+ *data_len = sizeof(res);
+ return IPMI_CC_OK;
+ }
+ catch (const std::exception& e)
+ {
+ const std::string e_str = std::string("wd_get: ") + e.what();
+ log<level::ERR>(e_str.c_str());
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ catch (...)
+ {
+ log<level::ERR>("wd_get: Unknown Error");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+}
diff --git a/app/watchdog.hpp b/app/watchdog.hpp
index c09bd1c..5359a33 100644
--- a/app/watchdog.hpp
+++ b/app/watchdog.hpp
@@ -39,3 +39,21 @@ ipmi_ret_t ipmi_app_watchdog_set(
ipmi_response_t response,
ipmi_data_len_t data_len,
ipmi_context_t context);
+
+/** @brief The GET watchdog IPMI command.
+ * @param[in] netfn
+ * @param[in] cmd
+ * @param[in] request
+ * @param[in,out] response
+ * @param[out] data_len
+ * @param[in] context
+ *
+ * @return IPMI_CC_OK on success, an IPMI error code otherwise.
+ */
+ipmi_ret_t ipmi_app_watchdog_get(
+ 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);
diff --git a/apphandler.cpp b/apphandler.cpp
index 47a165b..c452634 100644
--- a/apphandler.cpp
+++ b/apphandler.cpp
@@ -546,6 +546,13 @@ void register_netfn_app_functions()
ipmi_app_watchdog_set,
PRIVILEGE_OPERATOR);
+ // <Get Watchdog Timer>
+ ipmi_register_callback(NETFUN_APP,
+ IPMI_CMD_GET_WD,
+ NULL,
+ ipmi_app_watchdog_get,
+ PRIVILEGE_OPERATOR);
+
// <Get Device ID>
printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
NETFUN_APP,
diff --git a/apphandler.h b/apphandler.h
index 89bb51b..7e86442 100644
--- a/apphandler.h
+++ b/apphandler.h
@@ -13,6 +13,7 @@ enum ipmi_netfn_app_cmds
IPMI_CMD_GET_DEVICE_GUID = 0x08,
IPMI_CMD_RESET_WD = 0x22,
IPMI_CMD_SET_WD = 0x24,
+ IPMI_CMD_GET_WD = 0x25,
IPMI_CMD_GET_CAP_BIT = 0x36,
IPMI_CMD_GET_SYS_GUID = 0x37,
IPMI_CMD_SET_CHAN_ACCESS = 0x40,
diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
index 97544a0..5fa539a 100644
--- a/host-ipmid-whitelist.conf
+++ b/host-ipmid-whitelist.conf
@@ -12,6 +12,7 @@
0x06:0x08 //<App>:<Get Device GUID>
0x06:0x22 //<App>:<Reset Watchdog Timer>
0x06:0x24 //<App>:<Set Watchdog Timer>
+0x06:0x25 //<App>:<Get Watchdog Timer>
0x06:0x2E //<App>:<Set BMC Global Enables>
0x06:0x31 //<App>:<Get Message Flags>
0x06:0x35 //<App>:<Read Event Message Buffer>
OpenPOWER on IntegriCloud