1 #include "watchdog_service.hpp" 2 3 #include <phosphor-logging/elog.hpp> 4 #include <phosphor-logging/elog-errors.hpp> 5 #include <phosphor-logging/log.hpp> 6 #include <sdbusplus/bus.hpp> 7 #include <sdbusplus/message.hpp> 8 #include <string> 9 #include <xyz/openbmc_project/Common/error.hpp> 10 #include <xyz/openbmc_project/State/Watchdog/server.hpp> 11 12 #include "host-ipmid/ipmid-api.h" 13 14 using phosphor::logging::entry; 15 using phosphor::logging::elog; 16 using phosphor::logging::level; 17 using phosphor::logging::log; 18 using sdbusplus::message::variant_ns::get; 19 using sdbusplus::message::variant_ns::variant; 20 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 21 using sdbusplus::xyz::openbmc_project::State::server::convertForMessage; 22 using sdbusplus::xyz::openbmc_project::State::server::Watchdog; 23 24 static constexpr char wd_path[] = "/xyz/openbmc_project/watchdog/host0"; 25 static constexpr char wd_intf[] = "xyz.openbmc_project.State.Watchdog"; 26 static constexpr char prop_intf[] = "org.freedesktop.DBus.Properties"; 27 28 ipmi::ServiceCache WatchdogService::wd_service(wd_intf, wd_path); 29 30 WatchdogService::WatchdogService() 31 : bus(ipmid_get_sd_bus_connection()) 32 { 33 } 34 35 void WatchdogService::resetTimeRemaining(bool enableWatchdog) 36 { 37 bool wasValid = wd_service.isValid(bus); 38 auto request = wd_service.newMethodCall( 39 bus, wd_intf, "ResetTimeRemaining"); 40 request.append(enableWatchdog); 41 auto response = bus.call(request); 42 if (response.is_method_error()) 43 { 44 wd_service.invalidate(); 45 if (wasValid) 46 { 47 // Retry the request once in case the cached service was stale 48 return resetTimeRemaining(enableWatchdog); 49 } 50 log<level::ERR>( 51 "WatchdogService: Method error resetting time remaining", 52 entry("ENABLE_WATCHDOG=%d", !!enableWatchdog)); 53 elog<InternalFailure>(); 54 } 55 } 56 57 WatchdogService::Properties WatchdogService::getProperties() 58 { 59 bool wasValid = wd_service.isValid(bus); 60 auto request = wd_service.newMethodCall(bus, prop_intf, "GetAll"); 61 request.append(wd_intf); 62 auto response = bus.call(request); 63 if (response.is_method_error()) 64 { 65 wd_service.invalidate(); 66 if (wasValid) 67 { 68 // Retry the request once in case the cached service was stale 69 return getProperties(); 70 } 71 log<level::ERR>("WatchdogService: Method error getting properties"); 72 elog<InternalFailure>(); 73 } 74 75 std::map<std::string, variant<bool, uint64_t, std::string>> properties; 76 response.read(properties); 77 Properties wd_prop; 78 wd_prop.initialized = get<bool>(properties.at("Initialized")); 79 wd_prop.enabled = get<bool>(properties.at("Enabled")); 80 wd_prop.expireAction = Watchdog::convertActionFromString( 81 get<std::string>(properties.at("ExpireAction"))); 82 wd_prop.interval = get<uint64_t>(properties.at("Interval")); 83 wd_prop.timeRemaining = get<uint64_t>(properties.at("TimeRemaining")); 84 return wd_prop; 85 } 86 87 template <typename T> 88 T WatchdogService::getProperty(const std::string& key) 89 { 90 bool wasValid = wd_service.isValid(bus); 91 auto request = wd_service.newMethodCall(bus, prop_intf, "Get"); 92 request.append(wd_intf, key); 93 auto response = bus.call(request); 94 if (response.is_method_error()) 95 { 96 wd_service.invalidate(); 97 if (wasValid) 98 { 99 // Retry the request once in case the cached service was stale 100 return getProperty<T>(key); 101 } 102 log<level::ERR>("WatchdogService: Method error getting property", 103 entry("PROPERTY=%s", key.c_str())); 104 elog<InternalFailure>(); 105 } 106 variant<T> value; 107 response.read(value); 108 return get<T>(value); 109 } 110 111 template <typename T> 112 void WatchdogService::setProperty(const std::string& key, const T& val) 113 { 114 bool wasValid = wd_service.isValid(bus); 115 auto request = wd_service.newMethodCall(bus, prop_intf, "Set"); 116 request.append(wd_intf, key, variant<T>(val)); 117 auto response = bus.call(request); 118 if (response.is_method_error()) 119 { 120 wd_service.invalidate(); 121 if (wasValid) 122 { 123 // Retry the request once in case the cached service was stale 124 return setProperty(key, val); 125 } 126 log<level::ERR>("WatchdogService: Method error setting property", 127 entry("PROPERTY=%s", key.c_str())); 128 elog<InternalFailure>(); 129 } 130 } 131 132 bool WatchdogService::getInitialized() 133 { 134 return getProperty<bool>("Initialized"); 135 } 136 137 void WatchdogService::setInitialized(bool initialized) 138 { 139 setProperty("Initialized", initialized); 140 } 141 142 void WatchdogService::setEnabled(bool enabled) 143 { 144 setProperty("Enabled", enabled); 145 } 146 147 void WatchdogService::setExpireAction(Action expireAction) 148 { 149 setProperty("ExpireAction", convertForMessage(expireAction)); 150 } 151 152 void WatchdogService::setInterval(uint64_t interval) 153 { 154 setProperty("Interval", interval); 155 } 156 157 void WatchdogService::setTimeRemaining(uint64_t timeRemaining) 158 { 159 setProperty("TimeRemaining", timeRemaining); 160 } 161