blob: 0dad74f04fe3762c52e231f610d082b08d97270c [file] [log] [blame]
Patrick Venture5e6ac712017-10-25 12:16:19 -07001#include "watchdog.hpp"
2
3#include <systemd/sd-bus.h>
4#include <mapper.h>
5
6extern sd_bus *bus;
7
8struct set_wd_data_t {
9 uint8_t t_use;
10 uint8_t t_action;
11 uint8_t preset;
12 uint8_t flags;
13 uint8_t ls;
14 uint8_t ms;
15} __attribute__ ((packed));
16
17
18
19ipmi_ret_t ipmi_app_set_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
20 ipmi_request_t request, ipmi_response_t response,
21 ipmi_data_len_t data_len, ipmi_context_t context)
22{
23 const char *objname = "/xyz/openbmc_project/watchdog/host0";
24 const char *iface = "xyz.openbmc_project.State.Watchdog";
25 const char *property_iface = "org.freedesktop.DBus.Properties";
26 sd_bus_message *reply = NULL;
27 sd_bus_error error = SD_BUS_ERROR_NULL;
28 int r = 0;
29
30 set_wd_data_t *reqptr = (set_wd_data_t*) request;
31 uint16_t timer = 0;
32
33 // Making this uint64_t to match with provider
34 uint64_t timer_ms = 0;
35 char *busname = NULL;
36 *data_len = 0;
37
38 // Get number of 100ms intervals
39 timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls;
40 // Get timer value in ms
41 timer_ms = timer * 100;
42
43 printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer);
44
45 // Get bus name
46 r = mapper_get_service(bus, objname, &busname);
47 if (r < 0) {
48 fprintf(stderr, "Failed to get %s bus name: %s\n",
49 objname, strerror(-r));
50 goto finish;
51 }
52
53 // Disable watchdog if running
54 r = sd_bus_call_method(bus, busname, objname, property_iface,
55 "Set", &error, &reply, "ssv",
56 iface, "Enabled", "b", false);
57 if(r < 0) {
58 fprintf(stderr, "Failed to disable Watchdog: %s\n",
59 strerror(-r));
60 goto finish;
61 }
62
63 /*
64 * If the action is 0, it means, do nothing. Multiple actions on timer
65 * expiration aren't supported by phosphor-watchdog yet, so when the
66 * action set is "none", we should just leave the timer disabled.
67 */
68 if (0 == reqptr->t_action)
69 {
70 goto finish;
71 }
72
73 if (reqptr->t_use & 0x40)
74 {
75 sd_bus_error_free(&error);
76 reply = sd_bus_message_unref(reply);
77
78 // Set the Interval for the Watchdog
79 r = sd_bus_call_method(bus, busname, objname, property_iface,
80 "Set", &error, &reply, "ssv",
81 iface, "Interval", "t", timer_ms);
82 if(r < 0) {
83 fprintf(stderr, "Failed to set new expiration time: %s\n",
84 strerror(-r));
85 goto finish;
86 }
87
88 // Now Enable Watchdog
89 r = sd_bus_call_method(bus, busname, objname, property_iface,
90 "Set", &error, &reply, "ssv",
91 iface, "Enabled", "b", true);
92 if(r < 0) {
93 fprintf(stderr, "Failed to Enable Watchdog: %s\n",
94 strerror(-r));
95 goto finish;
96 }
97 }
98
99finish:
100 sd_bus_error_free(&error);
101 reply = sd_bus_message_unref(reply);
102 free(busname);
103
104 return (r < 0) ? -1 : IPMI_CC_OK;
105}
106
107
108ipmi_ret_t ipmi_app_reset_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
109 ipmi_request_t request, ipmi_response_t response,
110 ipmi_data_len_t data_len, ipmi_context_t context)
111{
112 const char *objname = "/xyz/openbmc_project/watchdog/host0";
113 const char *iface = "xyz.openbmc_project.State.Watchdog";
114 const char *property_iface = "org.freedesktop.DBus.Properties";
115 sd_bus_message *reply = NULL;
116 sd_bus_error error = SD_BUS_ERROR_NULL;
117 int r = 0;
118 char *busname = NULL;
119
120 // Current time interval that is set in watchdog.
121 uint64_t interval = 0;
122
123 // Status code.
124 ipmi_ret_t rc = IPMI_CC_OK;
125 *data_len = 0;
126
127 printf("WATCHDOG RESET\n");
128 // Get bus name
129 r = mapper_get_service(bus, objname, &busname);
130 if (r < 0) {
131 fprintf(stderr, "Failed to get %s bus name: %s\n",
132 objname, strerror(-r));
133 goto finish;
134 }
135
136 // Get the current interval and set it back.
137 r = sd_bus_call_method(bus, busname, objname, property_iface,
138 "Get", &error, &reply, "ss",
139 iface, "Interval");
140
141 if(r < 0) {
142 fprintf(stderr, "Failed to get current Interval msg: %s\n",
143 strerror(-r));
144 goto finish;
145 }
146
147 // Now extract the value
148 r = sd_bus_message_read(reply, "v", "t", &interval);
149 if (r < 0) {
150 fprintf(stderr, "Failed to read current interval: %s\n",
151 strerror(-r));
152 goto finish;
153 }
154
155 sd_bus_error_free(&error);
156 reply = sd_bus_message_unref(reply);
157
158 // Set watchdog timer
159 r = sd_bus_call_method(bus, busname, objname, property_iface,
160 "Set", &error, &reply, "ssv",
161 iface, "TimeRemaining", "t", interval);
162 if(r < 0) {
163 fprintf(stderr, "Failed to refresh the timer: %s\n",
164 strerror(-r));
165 goto finish;
166 }
167
168finish:
169 sd_bus_error_free(&error);
170 reply = sd_bus_message_unref(reply);
171 free(busname);
172
173 return rc;
174}