From 73f44518bdafd438f800d31d47ee9176d42cc83f Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Fri, 9 Feb 2018 15:28:46 -0800 Subject: watchdog: Implements the Watchdog Get Command Change-Id: I2ba9fd0eeba4e828cafd1bcf6fe30e2322eaf99e Signed-off-by: William A. Kennington III --- app/watchdog.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ app/watchdog.hpp | 18 +++++++++++ 2 files changed, 116 insertions(+) (limited to 'app') 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( + 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(e_str.c_str()); + return IPMI_CC_UNSPECIFIED_ERROR; + } + catch (...) + { + log("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); -- cgit v1.2.1