summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/watchdog.cpp174
-rw-r--r--app/watchdog.hpp32
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);
+
OpenPOWER on IntegriCloud