blob: c8c9ced89e9848b80de261cc2069cd23837caa78 [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
William A. Kennington III61d5f7b2018-02-09 15:23:53 -080024ipmi_ret_t ipmi_app_watchdog_reset(
Patrick Venture894571d2017-11-09 14:46:54 -080025 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 char *busname = NULL;
36
William A. Kennington III5325f2c2018-01-08 15:17:09 -080037 // Current properties of the watchdog daemon.
William A. Kennington IIIe73d15d2018-01-24 15:12:21 -080038 int enabled = 0;
Patrick Venture5e6ac712017-10-25 12:16:19 -070039 uint64_t interval = 0;
40
41 // Status code.
William A. Kennington III6ae3df32018-01-18 11:19:30 -080042 ipmi_ret_t ret = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture5e6ac712017-10-25 12:16:19 -070043 *data_len = 0;
44
45 printf("WATCHDOG RESET\n");
46 // Get bus name
47 r = mapper_get_service(bus, objname, &busname);
48 if (r < 0) {
49 fprintf(stderr, "Failed to get %s bus name: %s\n",
50 objname, strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080051 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -070052 goto finish;
53 }
54
William A. Kennington III5325f2c2018-01-08 15:17:09 -080055 // Check if our watchdog is running
56 r = sd_bus_call_method(bus, busname, objname, property_iface,
57 "Get", &error, &reply, "ss",
58 iface, "Enabled");
59 if(r < 0) {
60 fprintf(stderr, "Failed to get current Enabled msg: %s\n",
61 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080062 ret = IPMI_CC_BUSY;
William A. Kennington III5325f2c2018-01-08 15:17:09 -080063 goto finish;
64 }
65
66 // Now extract the value
67 r = sd_bus_message_read(reply, "v", "b", &enabled);
68 if (r < 0) {
69 fprintf(stderr, "Failed to read current Enabled: %s\n",
70 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080071 ret = IPMI_CC_BUSY;
William A. Kennington III5325f2c2018-01-08 15:17:09 -080072 goto finish;
73 }
74
75 // If we are not enable we should indicate that
76 if (!enabled) {
77 printf("Watchdog not enabled during reset\n");
William A. Kennington III6ae3df32018-01-18 11:19:30 -080078 ret = IPMI_WDOG_CC_NOT_INIT;
William A. Kennington III5325f2c2018-01-08 15:17:09 -080079 goto finish;
80 }
81
82 sd_bus_error_free(&error);
83 reply = sd_bus_message_unref(reply);
84
Patrick Venture5e6ac712017-10-25 12:16:19 -070085 // Get the current interval and set it back.
86 r = sd_bus_call_method(bus, busname, objname, property_iface,
87 "Get", &error, &reply, "ss",
88 iface, "Interval");
89
90 if(r < 0) {
91 fprintf(stderr, "Failed to get current Interval msg: %s\n",
92 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080093 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -070094 goto finish;
95 }
96
97 // Now extract the value
98 r = sd_bus_message_read(reply, "v", "t", &interval);
99 if (r < 0) {
100 fprintf(stderr, "Failed to read current interval: %s\n",
101 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800102 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700103 goto finish;
104 }
105
106 sd_bus_error_free(&error);
107 reply = sd_bus_message_unref(reply);
108
109 // Set watchdog timer
110 r = sd_bus_call_method(bus, busname, objname, property_iface,
111 "Set", &error, &reply, "ssv",
112 iface, "TimeRemaining", "t", interval);
113 if(r < 0) {
114 fprintf(stderr, "Failed to refresh the timer: %s\n",
115 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800116 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700117 goto finish;
118 }
119
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800120 ret = IPMI_CC_OK;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700121finish:
122 sd_bus_error_free(&error);
123 reply = sd_bus_message_unref(reply);
124 free(busname);
125
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800126 return ret;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700127}
William A. Kennington III61d5f7b2018-02-09 15:23:53 -0800128
129ipmi_ret_t ipmi_app_watchdog_set(
130 ipmi_netfn_t netfn,
131 ipmi_cmd_t cmd,
132 ipmi_request_t request,
133 ipmi_response_t response,
134 ipmi_data_len_t data_len,
135 ipmi_context_t context)
136{
137 sd_bus_message *reply = NULL;
138 sd_bus_error error = SD_BUS_ERROR_NULL;
139 int r = 0;
140 ipmi_ret_t ret = IPMI_CC_UNSPECIFIED_ERROR;
141
142 set_wd_data_t *reqptr = (set_wd_data_t*) request;
143
144 uint16_t timer = 0;
145
146 // Making this uint64_t to match with provider
147 uint64_t timer_ms = 0;
148 char *busname = NULL;
149 *data_len = 0;
150
151 // Get number of 100ms intervals
152 timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls;
153 // Get timer value in ms
154 timer_ms = timer * 100;
155
156 printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer);
157
158 // Get bus name
159 r = mapper_get_service(bus, objname, &busname);
160 if (r < 0) {
161 fprintf(stderr, "Failed to get %s bus name: %s\n",
162 objname, strerror(-r));
163 ret = IPMI_CC_BUSY;
164 goto finish;
165 }
166
167 // Disable watchdog if running
168 r = sd_bus_call_method(bus, busname, objname, property_iface,
169 "Set", &error, &reply, "ssv",
170 iface, "Enabled", "b", false);
171 if(r < 0) {
172 fprintf(stderr, "Failed to disable Watchdog: %s\n",
173 strerror(-r));
174 ret = IPMI_CC_BUSY;
175 goto finish;
176 }
177
178 /*
179 * If the action is 0, it means, do nothing. Multiple actions on timer
180 * expiration aren't supported by phosphor-watchdog yet, so when the
181 * action set is "none", we should just leave the timer disabled.
182 */
183 if (0 == reqptr->timer_action)
184 {
185 ret = IPMI_CC_OK;
186 goto finish;
187 }
188
189 if (reqptr->timer_use & 0x40)
190 {
191 sd_bus_error_free(&error);
192 reply = sd_bus_message_unref(reply);
193
194 // Set the Interval for the Watchdog
195 r = sd_bus_call_method(bus, busname, objname, property_iface,
196 "Set", &error, &reply, "ssv",
197 iface, "Interval", "t", timer_ms);
198 if(r < 0) {
199 fprintf(stderr, "Failed to set new expiration time: %s\n",
200 strerror(-r));
201 ret = IPMI_CC_BUSY;
202 goto finish;
203 }
204
205 // Now Enable Watchdog
206 r = sd_bus_call_method(bus, busname, objname, property_iface,
207 "Set", &error, &reply, "ssv",
208 iface, "Enabled", "b", true);
209 if(r < 0) {
210 fprintf(stderr, "Failed to Enable Watchdog: %s\n",
211 strerror(-r));
212 ret = IPMI_CC_BUSY;
213 goto finish;
214 }
215 }
216
217 ret = IPMI_CC_OK;
218finish:
219 sd_bus_error_free(&error);
220 reply = sd_bus_message_unref(reply);
221 free(busname);
222
223 return ret;
224}