1 #include "watchdog.hpp" 2 #include "utils.hpp" 3 4 #include <systemd/sd-bus.h> 5 6 #include <mapper.h> 7 #include <sdbusplus/bus.hpp> 8 9 extern sd_bus *bus; 10 11 struct set_wd_data_t { 12 uint8_t timer_use; 13 uint8_t timer_action; 14 uint8_t preset; 15 uint8_t flags; 16 uint8_t ls; 17 uint8_t ms; 18 } __attribute__ ((packed)); 19 20 static constexpr auto objname = "/xyz/openbmc_project/watchdog/host0"; 21 static constexpr auto iface = "xyz.openbmc_project.State.Watchdog"; 22 static constexpr auto property_iface = "org.freedesktop.DBus.Properties"; 23 24 ipmi_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) 31 { 32 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; 37 38 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 */ 75 if (0 == reqptr->timer_action) 76 { 77 goto finish; 78 } 79 80 if (reqptr->timer_use & 0x40) 81 { 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 106 finish: 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 114 ipmi_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) 121 { 122 sd_bus_message *reply = NULL; 123 sd_bus_error error = SD_BUS_ERROR_NULL; 124 int r = 0; 125 char *busname = NULL; 126 127 // Current time interval that is set in watchdog. 128 uint64_t interval = 0; 129 130 // Status code. 131 ipmi_ret_t rc = IPMI_CC_OK; 132 *data_len = 0; 133 134 printf("WATCHDOG RESET\n"); 135 // Get bus name 136 r = mapper_get_service(bus, objname, &busname); 137 if (r < 0) { 138 fprintf(stderr, "Failed to get %s bus name: %s\n", 139 objname, strerror(-r)); 140 goto finish; 141 } 142 143 // Get the current interval and set it back. 144 r = sd_bus_call_method(bus, busname, objname, property_iface, 145 "Get", &error, &reply, "ss", 146 iface, "Interval"); 147 148 if(r < 0) { 149 fprintf(stderr, "Failed to get current Interval msg: %s\n", 150 strerror(-r)); 151 goto finish; 152 } 153 154 // Now extract the value 155 r = sd_bus_message_read(reply, "v", "t", &interval); 156 if (r < 0) { 157 fprintf(stderr, "Failed to read current interval: %s\n", 158 strerror(-r)); 159 goto finish; 160 } 161 162 sd_bus_error_free(&error); 163 reply = sd_bus_message_unref(reply); 164 165 // Set watchdog timer 166 r = sd_bus_call_method(bus, busname, objname, property_iface, 167 "Set", &error, &reply, "ssv", 168 iface, "TimeRemaining", "t", interval); 169 if(r < 0) { 170 fprintf(stderr, "Failed to refresh the timer: %s\n", 171 strerror(-r)); 172 goto finish; 173 } 174 175 finish: 176 sd_bus_error_free(&error); 177 reply = sd_bus_message_unref(reply); 178 free(busname); 179 180 return rc; 181 } 182