diff options
-rw-r--r-- | app/watchdog.cpp | 98 | ||||
-rw-r--r-- | app/watchdog.hpp | 18 | ||||
-rw-r--r-- | apphandler.cpp | 7 | ||||
-rw-r--r-- | apphandler.h | 1 | ||||
-rw-r--r-- | host-ipmid-whitelist.conf | 1 |
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> |