blob: 7b04faaa772aef5d69d0896ffa9bbfac2571f8de [file] [log] [blame]
Patrick Venture5e6ac712017-10-25 12:16:19 -07001#include "watchdog.hpp"
Patrick Venture894571d2017-11-09 14:46:54 -08002#include "utils.hpp"
Patrick Venture5e6ac712017-10-25 12:16:19 -07003
4#include <systemd/sd-bus.h>
Patrick Venture894571d2017-11-09 14:46:54 -08005
Patrick Venture5e6ac712017-10-25 12:16:19 -07006#include <mapper.h>
Patrick Venture894571d2017-11-09 14:46:54 -08007#include <sdbusplus/bus.hpp>
Patrick Venture5e6ac712017-10-25 12:16:19 -07008
9extern sd_bus *bus;
10
11struct set_wd_data_t {
Patrick Venture894571d2017-11-09 14:46:54 -080012 uint8_t timer_use;
13 uint8_t timer_action;
Patrick Venture5e6ac712017-10-25 12:16:19 -070014 uint8_t preset;
15 uint8_t flags;
16 uint8_t ls;
17 uint8_t ms;
18} __attribute__ ((packed));
19
Patrick Venture894571d2017-11-09 14:46:54 -080020static constexpr auto objname = "/xyz/openbmc_project/watchdog/host0";
21static constexpr auto iface = "xyz.openbmc_project.State.Watchdog";
22static constexpr auto property_iface = "org.freedesktop.DBus.Properties";
Patrick Venture5e6ac712017-10-25 12:16:19 -070023
Patrick Venture894571d2017-11-09 14:46:54 -080024ipmi_ret_t ipmi_app_set_watchdog(
25 ipmi_netfn_t netfn,
26 ipmi_cmd_t cmd,
27 ipmi_request_t request,
28 ipmi_response_t response,
29 ipmi_data_len_t data_len,
30 ipmi_context_t context)
Patrick Venture5e6ac712017-10-25 12:16:19 -070031{
Patrick Venture5e6ac712017-10-25 12:16:19 -070032 sd_bus_message *reply = NULL;
33 sd_bus_error error = SD_BUS_ERROR_NULL;
34 int r = 0;
35
36 set_wd_data_t *reqptr = (set_wd_data_t*) request;
Patrick Venture894571d2017-11-09 14:46:54 -080037
Patrick Venture5e6ac712017-10-25 12:16:19 -070038 uint16_t timer = 0;
39
40 // Making this uint64_t to match with provider
41 uint64_t timer_ms = 0;
42 char *busname = NULL;
43 *data_len = 0;
44
45 // Get number of 100ms intervals
46 timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls;
47 // Get timer value in ms
48 timer_ms = timer * 100;
49
50 printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer);
51
52 // Get bus name
53 r = mapper_get_service(bus, objname, &busname);
54 if (r < 0) {
55 fprintf(stderr, "Failed to get %s bus name: %s\n",
56 objname, strerror(-r));
57 goto finish;
58 }
59
60 // Disable watchdog if running
61 r = sd_bus_call_method(bus, busname, objname, property_iface,
62 "Set", &error, &reply, "ssv",
63 iface, "Enabled", "b", false);
64 if(r < 0) {
65 fprintf(stderr, "Failed to disable Watchdog: %s\n",
66 strerror(-r));
67 goto finish;
68 }
69
70 /*
71 * If the action is 0, it means, do nothing. Multiple actions on timer
72 * expiration aren't supported by phosphor-watchdog yet, so when the
73 * action set is "none", we should just leave the timer disabled.
74 */
Patrick Venture894571d2017-11-09 14:46:54 -080075 if (0 == reqptr->timer_action)
Patrick Venture5e6ac712017-10-25 12:16:19 -070076 {
77 goto finish;
78 }
79
Patrick Venture894571d2017-11-09 14:46:54 -080080 if (reqptr->timer_use & 0x40)
Patrick Venture5e6ac712017-10-25 12:16:19 -070081 {
82 sd_bus_error_free(&error);
83 reply = sd_bus_message_unref(reply);
84
85 // Set the Interval for the Watchdog
86 r = sd_bus_call_method(bus, busname, objname, property_iface,
87 "Set", &error, &reply, "ssv",
88 iface, "Interval", "t", timer_ms);
89 if(r < 0) {
90 fprintf(stderr, "Failed to set new expiration time: %s\n",
91 strerror(-r));
92 goto finish;
93 }
94
95 // Now Enable Watchdog
96 r = sd_bus_call_method(bus, busname, objname, property_iface,
97 "Set", &error, &reply, "ssv",
98 iface, "Enabled", "b", true);
99 if(r < 0) {
100 fprintf(stderr, "Failed to Enable Watchdog: %s\n",
101 strerror(-r));
102 goto finish;
103 }
104 }
105
106finish:
107 sd_bus_error_free(&error);
108 reply = sd_bus_message_unref(reply);
109 free(busname);
110
111 return (r < 0) ? -1 : IPMI_CC_OK;
112}
113
Patrick Venture894571d2017-11-09 14:46:54 -0800114ipmi_ret_t ipmi_app_reset_watchdog(
115 ipmi_netfn_t netfn,
116 ipmi_cmd_t cmd,
117 ipmi_request_t request,
118 ipmi_response_t response,
119 ipmi_data_len_t data_len,
120 ipmi_context_t context)
Patrick Venture5e6ac712017-10-25 12:16:19 -0700121{
Patrick Venture5e6ac712017-10-25 12:16:19 -0700122 sd_bus_message *reply = NULL;
123 sd_bus_error error = SD_BUS_ERROR_NULL;
124 int r = 0;
125 char *busname = NULL;
126
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800127 // Current properties of the watchdog daemon.
128 bool enabled = false;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700129 uint64_t interval = 0;
130
131 // Status code.
132 ipmi_ret_t rc = IPMI_CC_OK;
133 *data_len = 0;
134
135 printf("WATCHDOG RESET\n");
136 // Get bus name
137 r = mapper_get_service(bus, objname, &busname);
138 if (r < 0) {
139 fprintf(stderr, "Failed to get %s bus name: %s\n",
140 objname, strerror(-r));
141 goto finish;
142 }
143
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800144 // Check if our watchdog is running
145 r = sd_bus_call_method(bus, busname, objname, property_iface,
146 "Get", &error, &reply, "ss",
147 iface, "Enabled");
148 if(r < 0) {
149 fprintf(stderr, "Failed to get current Enabled msg: %s\n",
150 strerror(-r));
151 goto finish;
152 }
153
154 // Now extract the value
155 r = sd_bus_message_read(reply, "v", "b", &enabled);
156 if (r < 0) {
157 fprintf(stderr, "Failed to read current Enabled: %s\n",
158 strerror(-r));
159 goto finish;
160 }
161
162 // If we are not enable we should indicate that
163 if (!enabled) {
164 printf("Watchdog not enabled during reset\n");
165 rc = IPMI_WDOG_CC_NOT_INIT;
166 goto finish;
167 }
168
169 sd_bus_error_free(&error);
170 reply = sd_bus_message_unref(reply);
171
Patrick Venture5e6ac712017-10-25 12:16:19 -0700172 // Get the current interval and set it back.
173 r = sd_bus_call_method(bus, busname, objname, property_iface,
174 "Get", &error, &reply, "ss",
175 iface, "Interval");
176
177 if(r < 0) {
178 fprintf(stderr, "Failed to get current Interval msg: %s\n",
179 strerror(-r));
180 goto finish;
181 }
182
183 // Now extract the value
184 r = sd_bus_message_read(reply, "v", "t", &interval);
185 if (r < 0) {
186 fprintf(stderr, "Failed to read current interval: %s\n",
187 strerror(-r));
188 goto finish;
189 }
190
191 sd_bus_error_free(&error);
192 reply = sd_bus_message_unref(reply);
193
194 // Set watchdog timer
195 r = sd_bus_call_method(bus, busname, objname, property_iface,
196 "Set", &error, &reply, "ssv",
197 iface, "TimeRemaining", "t", interval);
198 if(r < 0) {
199 fprintf(stderr, "Failed to refresh the timer: %s\n",
200 strerror(-r));
201 goto finish;
202 }
203
204finish:
205 sd_bus_error_free(&error);
206 reply = sd_bus_message_unref(reply);
207 free(busname);
208
209 return rc;
210}