blob: 6870aaafe37579af9ba325bb167b18b95a9b97cd [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;
William A. Kennington III6ae3df32018-01-18 11:19:30 -080035 ipmi_ret_t ret = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture5e6ac712017-10-25 12:16:19 -070036
37 set_wd_data_t *reqptr = (set_wd_data_t*) request;
Patrick Venture894571d2017-11-09 14:46:54 -080038
Patrick Venture5e6ac712017-10-25 12:16:19 -070039 uint16_t timer = 0;
40
41 // Making this uint64_t to match with provider
42 uint64_t timer_ms = 0;
43 char *busname = NULL;
44 *data_len = 0;
45
46 // Get number of 100ms intervals
47 timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls;
48 // Get timer value in ms
49 timer_ms = timer * 100;
50
51 printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer);
52
53 // Get bus name
54 r = mapper_get_service(bus, objname, &busname);
55 if (r < 0) {
56 fprintf(stderr, "Failed to get %s bus name: %s\n",
57 objname, strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080058 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -070059 goto finish;
60 }
61
62 // Disable watchdog if running
63 r = sd_bus_call_method(bus, busname, objname, property_iface,
64 "Set", &error, &reply, "ssv",
65 iface, "Enabled", "b", false);
66 if(r < 0) {
67 fprintf(stderr, "Failed to disable Watchdog: %s\n",
68 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080069 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -070070 goto finish;
71 }
72
73 /*
74 * If the action is 0, it means, do nothing. Multiple actions on timer
75 * expiration aren't supported by phosphor-watchdog yet, so when the
76 * action set is "none", we should just leave the timer disabled.
77 */
Patrick Venture894571d2017-11-09 14:46:54 -080078 if (0 == reqptr->timer_action)
Patrick Venture5e6ac712017-10-25 12:16:19 -070079 {
William A. Kennington III6ae3df32018-01-18 11:19:30 -080080 ret = IPMI_CC_OK;
Patrick Venture5e6ac712017-10-25 12:16:19 -070081 goto finish;
82 }
83
Patrick Venture894571d2017-11-09 14:46:54 -080084 if (reqptr->timer_use & 0x40)
Patrick Venture5e6ac712017-10-25 12:16:19 -070085 {
86 sd_bus_error_free(&error);
87 reply = sd_bus_message_unref(reply);
88
89 // Set the Interval for the Watchdog
90 r = sd_bus_call_method(bus, busname, objname, property_iface,
91 "Set", &error, &reply, "ssv",
92 iface, "Interval", "t", timer_ms);
93 if(r < 0) {
94 fprintf(stderr, "Failed to set new expiration time: %s\n",
95 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -080096 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -070097 goto finish;
98 }
99
100 // Now Enable Watchdog
101 r = sd_bus_call_method(bus, busname, objname, property_iface,
102 "Set", &error, &reply, "ssv",
103 iface, "Enabled", "b", true);
104 if(r < 0) {
105 fprintf(stderr, "Failed to Enable Watchdog: %s\n",
106 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800107 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700108 goto finish;
109 }
110 }
111
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800112 ret = IPMI_CC_OK;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700113finish:
114 sd_bus_error_free(&error);
115 reply = sd_bus_message_unref(reply);
116 free(busname);
117
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800118 return ret;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700119}
120
Patrick Venture894571d2017-11-09 14:46:54 -0800121ipmi_ret_t ipmi_app_reset_watchdog(
122 ipmi_netfn_t netfn,
123 ipmi_cmd_t cmd,
124 ipmi_request_t request,
125 ipmi_response_t response,
126 ipmi_data_len_t data_len,
127 ipmi_context_t context)
Patrick Venture5e6ac712017-10-25 12:16:19 -0700128{
Patrick Venture5e6ac712017-10-25 12:16:19 -0700129 sd_bus_message *reply = NULL;
130 sd_bus_error error = SD_BUS_ERROR_NULL;
131 int r = 0;
132 char *busname = NULL;
133
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800134 // Current properties of the watchdog daemon.
William A. Kennington IIIe73d15d2018-01-24 15:12:21 -0800135 int enabled = 0;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700136 uint64_t interval = 0;
137
138 // Status code.
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800139 ipmi_ret_t ret = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700140 *data_len = 0;
141
142 printf("WATCHDOG RESET\n");
143 // Get bus name
144 r = mapper_get_service(bus, objname, &busname);
145 if (r < 0) {
146 fprintf(stderr, "Failed to get %s bus name: %s\n",
147 objname, strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800148 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700149 goto finish;
150 }
151
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800152 // Check if our watchdog is running
153 r = sd_bus_call_method(bus, busname, objname, property_iface,
154 "Get", &error, &reply, "ss",
155 iface, "Enabled");
156 if(r < 0) {
157 fprintf(stderr, "Failed to get current Enabled msg: %s\n",
158 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800159 ret = IPMI_CC_BUSY;
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800160 goto finish;
161 }
162
163 // Now extract the value
164 r = sd_bus_message_read(reply, "v", "b", &enabled);
165 if (r < 0) {
166 fprintf(stderr, "Failed to read current Enabled: %s\n",
167 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800168 ret = IPMI_CC_BUSY;
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800169 goto finish;
170 }
171
172 // If we are not enable we should indicate that
173 if (!enabled) {
174 printf("Watchdog not enabled during reset\n");
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800175 ret = IPMI_WDOG_CC_NOT_INIT;
William A. Kennington III5325f2c2018-01-08 15:17:09 -0800176 goto finish;
177 }
178
179 sd_bus_error_free(&error);
180 reply = sd_bus_message_unref(reply);
181
Patrick Venture5e6ac712017-10-25 12:16:19 -0700182 // Get the current interval and set it back.
183 r = sd_bus_call_method(bus, busname, objname, property_iface,
184 "Get", &error, &reply, "ss",
185 iface, "Interval");
186
187 if(r < 0) {
188 fprintf(stderr, "Failed to get current Interval msg: %s\n",
189 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800190 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700191 goto finish;
192 }
193
194 // Now extract the value
195 r = sd_bus_message_read(reply, "v", "t", &interval);
196 if (r < 0) {
197 fprintf(stderr, "Failed to read current interval: %s\n",
198 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800199 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700200 goto finish;
201 }
202
203 sd_bus_error_free(&error);
204 reply = sd_bus_message_unref(reply);
205
206 // Set watchdog timer
207 r = sd_bus_call_method(bus, busname, objname, property_iface,
208 "Set", &error, &reply, "ssv",
209 iface, "TimeRemaining", "t", interval);
210 if(r < 0) {
211 fprintf(stderr, "Failed to refresh the timer: %s\n",
212 strerror(-r));
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800213 ret = IPMI_CC_BUSY;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700214 goto finish;
215 }
216
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800217 ret = IPMI_CC_OK;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700218finish:
219 sd_bus_error_free(&error);
220 reply = sd_bus_message_unref(reply);
221 free(busname);
222
William A. Kennington III6ae3df32018-01-18 11:19:30 -0800223 return ret;
Patrick Venture5e6ac712017-10-25 12:16:19 -0700224}