diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/watchdog.cpp | 174 | ||||
-rw-r--r-- | app/watchdog.hpp | 32 |
2 files changed, 206 insertions, 0 deletions
diff --git a/app/watchdog.cpp b/app/watchdog.cpp new file mode 100644 index 0000000..0dad74f --- /dev/null +++ b/app/watchdog.cpp @@ -0,0 +1,174 @@ +#include "watchdog.hpp" + +#include <systemd/sd-bus.h> +#include <mapper.h> + +extern sd_bus *bus; + +struct set_wd_data_t { + uint8_t t_use; + uint8_t t_action; + uint8_t preset; + uint8_t flags; + uint8_t ls; + uint8_t ms; +} __attribute__ ((packed)); + + + +ipmi_ret_t ipmi_app_set_watchdog(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) +{ + const char *objname = "/xyz/openbmc_project/watchdog/host0"; + const char *iface = "xyz.openbmc_project.State.Watchdog"; + const char *property_iface = "org.freedesktop.DBus.Properties"; + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + + set_wd_data_t *reqptr = (set_wd_data_t*) request; + uint16_t timer = 0; + + // Making this uint64_t to match with provider + uint64_t timer_ms = 0; + char *busname = NULL; + *data_len = 0; + + // Get number of 100ms intervals + timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls; + // Get timer value in ms + timer_ms = timer * 100; + + printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer); + + // Get bus name + r = mapper_get_service(bus, objname, &busname); + if (r < 0) { + fprintf(stderr, "Failed to get %s bus name: %s\n", + objname, strerror(-r)); + goto finish; + } + + // Disable watchdog if running + r = sd_bus_call_method(bus, busname, objname, property_iface, + "Set", &error, &reply, "ssv", + iface, "Enabled", "b", false); + if(r < 0) { + fprintf(stderr, "Failed to disable Watchdog: %s\n", + strerror(-r)); + goto finish; + } + + /* + * If the action is 0, it means, do nothing. Multiple actions on timer + * expiration aren't supported by phosphor-watchdog yet, so when the + * action set is "none", we should just leave the timer disabled. + */ + if (0 == reqptr->t_action) + { + goto finish; + } + + if (reqptr->t_use & 0x40) + { + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + // Set the Interval for the Watchdog + r = sd_bus_call_method(bus, busname, objname, property_iface, + "Set", &error, &reply, "ssv", + iface, "Interval", "t", timer_ms); + if(r < 0) { + fprintf(stderr, "Failed to set new expiration time: %s\n", + strerror(-r)); + goto finish; + } + + // Now Enable Watchdog + r = sd_bus_call_method(bus, busname, objname, property_iface, + "Set", &error, &reply, "ssv", + iface, "Enabled", "b", true); + if(r < 0) { + fprintf(stderr, "Failed to Enable Watchdog: %s\n", + strerror(-r)); + goto finish; + } + } + +finish: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + free(busname); + + return (r < 0) ? -1 : IPMI_CC_OK; +} + + +ipmi_ret_t ipmi_app_reset_watchdog(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) +{ + const char *objname = "/xyz/openbmc_project/watchdog/host0"; + const char *iface = "xyz.openbmc_project.State.Watchdog"; + const char *property_iface = "org.freedesktop.DBus.Properties"; + sd_bus_message *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + char *busname = NULL; + + // Current time interval that is set in watchdog. + uint64_t interval = 0; + + // Status code. + ipmi_ret_t rc = IPMI_CC_OK; + *data_len = 0; + + printf("WATCHDOG RESET\n"); + // Get bus name + r = mapper_get_service(bus, objname, &busname); + if (r < 0) { + fprintf(stderr, "Failed to get %s bus name: %s\n", + objname, strerror(-r)); + goto finish; + } + + // Get the current interval and set it back. + r = sd_bus_call_method(bus, busname, objname, property_iface, + "Get", &error, &reply, "ss", + iface, "Interval"); + + if(r < 0) { + fprintf(stderr, "Failed to get current Interval msg: %s\n", + strerror(-r)); + goto finish; + } + + // Now extract the value + r = sd_bus_message_read(reply, "v", "t", &interval); + if (r < 0) { + fprintf(stderr, "Failed to read current interval: %s\n", + strerror(-r)); + goto finish; + } + + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + + // Set watchdog timer + r = sd_bus_call_method(bus, busname, objname, property_iface, + "Set", &error, &reply, "ssv", + iface, "TimeRemaining", "t", interval); + if(r < 0) { + fprintf(stderr, "Failed to refresh the timer: %s\n", + strerror(-r)); + goto finish; + } + +finish: + sd_bus_error_free(&error); + reply = sd_bus_message_unref(reply); + free(busname); + + return rc; +} diff --git a/app/watchdog.hpp b/app/watchdog.hpp new file mode 100644 index 0000000..059a4e7 --- /dev/null +++ b/app/watchdog.hpp @@ -0,0 +1,32 @@ +#include "ipmid.hpp" + +/** @brief The SET 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, -1 otherwise. + */ +ipmi_ret_t ipmi_app_set_watchdog(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); + +/** @brief The RESET 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, -1 otherwise. + */ +ipmi_ret_t ipmi_app_reset_watchdog(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); + |