diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | app/watchdog.cpp | 174 | ||||
-rw-r--r-- | app/watchdog.hpp | 32 | ||||
-rw-r--r-- | apphandler.cpp | 170 |
4 files changed, 208 insertions, 169 deletions
diff --git a/Makefile.am b/Makefile.am index 2c78f79..9eef999 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,7 @@ fru-read-gen.cpp: libapphandlerdir = ${libdir}/ipmid-providers libapphandler_LTLIBRARIES = libapphandler.la libapphandler_la_SOURCES = \ + app/watchdog.cpp \ apphandler.cpp \ sensorhandler.cpp \ storagehandler.cpp \ 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); + diff --git a/apphandler.cpp b/apphandler.cpp index 29adfa4..f1cd2dd 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -1,4 +1,5 @@ #include "apphandler.h" +#include "app/watchdog.hpp" #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" #include "types.hpp" @@ -365,175 +366,6 @@ ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } - -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; -} - extern struct ChannelConfig_t channelConfig; ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, |