1 #include <util/dbus.hpp> 2 #include <util/trace.hpp> 3 #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> 4 5 namespace util 6 { 7 8 namespace dbus 9 { 10 11 //------------------------------------------------------------------------------ 12 13 constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper"; 14 constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper"; 15 constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper"; 16 17 /** @brief Find the path and service that implements the given interface */ 18 int find(const std::string& i_interface, std::string& o_path, 19 std::string& o_service) 20 { 21 int rc = 1; // assume not success 22 23 auto bus = sdbusplus::bus::new_default(); 24 25 try 26 { 27 constexpr auto function = "GetSubTree"; 28 29 auto method = bus.new_method_call(objectMapperService, objectMapperPath, 30 objectMapperInterface, function); 31 32 // Search the entire dbus tree for the specified interface 33 method.append(std::string{"/"}, 0, 34 std::vector<std::string>{i_interface}); 35 36 auto reply = bus.call(method); 37 38 DBusSubTree response; 39 reply.read(response); 40 41 if (!response.empty()) 42 { 43 // Response is a map of object paths to a map of service, interfaces 44 auto object = *(response.begin()); 45 o_path = object.first; // return path 46 o_service = object.second.begin()->first; // return service 47 48 rc = 0; // success 49 } 50 } 51 catch (const sdbusplus::exception::SdBusError& e) 52 { 53 trace::err("util::dbus::find exception"); 54 std::string traceMsg = std::string(e.what()); 55 trace::err(traceMsg.c_str()); 56 } 57 58 return rc; 59 } 60 61 /** @brief Find the service that implements the given object and interface */ 62 int findService(const std::string& i_interface, const std::string& i_path, 63 std::string& o_service) 64 { 65 int rc = 1; // assume not success 66 67 auto bus = sdbusplus::bus::new_default(); 68 69 try 70 { 71 constexpr auto function = "GetObject"; 72 73 auto method = bus.new_method_call(objectMapperService, objectMapperPath, 74 objectMapperInterface, function); 75 76 // Find services that implement the object path, constrain the search 77 // to the given interface. 78 method.append(i_path, std::vector<std::string>{i_interface}); 79 80 auto reply = bus.call(method); 81 82 // response is a map of service names to their interfaces 83 std::map<DBusService, DBusInterfaceList> response; 84 reply.read(response); 85 86 if (!response.empty()) 87 { 88 // return the service 89 o_service = response.begin()->first; 90 91 rc = 0; // success 92 } 93 } 94 catch (const sdbusplus::exception::SdBusError& e) 95 { 96 trace::err("util::dbus::map exception"); 97 std::string traceMsg = std::string(e.what()); 98 trace::err(traceMsg.c_str()); 99 } 100 101 return rc; 102 } 103 104 /** @brief Read a property from a dbus object interface */ 105 int getProperty(const std::string& i_interface, const std::string& i_path, 106 const std::string& i_service, const std::string& i_property, 107 DBusValue& o_response) 108 { 109 int rc = 1; // assume not success 110 111 auto bus = sdbusplus::bus::new_default(); 112 113 try 114 { 115 constexpr auto interface = "org.freedesktop.DBus.Properties"; 116 constexpr auto function = "Get"; 117 118 // calling the get property method 119 auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(), 120 interface, function); 121 122 method.append(i_interface, i_property); 123 auto reply = bus.call(method); 124 125 // returning the property value 126 reply.read(o_response); 127 128 rc = 0; // success 129 } 130 catch (const sdbusplus::exception::SdBusError& e) 131 { 132 trace::err("util::dbus::getProperty exception"); 133 std::string traceMsg = std::string(e.what()); 134 trace::err(traceMsg.c_str()); 135 } 136 137 return rc; 138 } 139 140 /** @brief Get the IBM compatible names defined for this system */ 141 std::vector<std::string> systemNames() 142 { 143 std::vector<std::string> names; 144 145 constexpr auto interface = 146 "xyz.openbmc_project.Configuration.IBMCompatibleSystem"; 147 148 DBusService service; 149 DBusPath path; 150 151 // find a dbus object and path that implements the interface 152 if (0 == find(interface, path, service)) 153 { 154 DBusValue value; 155 156 // compatible system names are implemented as a property 157 constexpr auto property = "Names"; 158 159 if (0 == getProperty(interface, path, service, property, value)) 160 { 161 // return value is a variant, names are in the vector 162 names = std::get<std::vector<std::string>>(value); 163 } 164 } 165 166 return names; 167 } 168 169 /** @brief Transition the host state */ 170 void transitionHost(const HostState i_hostState) 171 { 172 try 173 { 174 // We will be transitioning host by starting appropriate dbus target 175 std::string target = "obmc-host-quiesce@0.target"; // quiesce is default 176 177 // crash (mpipl) mode state requested 178 if (HostState::Crash == i_hostState) 179 { 180 target = "obmc-host-crash@0.target"; 181 } 182 183 auto bus = sdbusplus::bus::new_system(); 184 auto method = bus.new_method_call( 185 "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 186 "org.freedesktop.systemd1.Manager", "StartUnit"); 187 188 method.append(target); // target unit to start 189 method.append("replace"); // mode = replace conflicting queued jobs 190 191 bus.call_noreply(method); // start the service 192 } 193 catch (const sdbusplus::exception::SdBusError& e) 194 { 195 trace::err("util::dbus::transitionHost exception"); 196 std::string traceMsg = std::string(e.what()); 197 trace::err(traceMsg.c_str()); 198 } 199 } 200 201 /** @brief Read state of autoreboot propertyi via dbus */ 202 bool autoRebootEnabled() 203 { 204 bool autoReboot = false; // assume autoreboot attribute not available 205 206 constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy"; 207 208 DBusService service; 209 DBusPath path; 210 211 // find a dbus object and path that implements the interface 212 if (0 == find(interface, path, service)) 213 { 214 DBusValue value; 215 216 // autoreboot policy is implemented as a property 217 constexpr auto property = "AutoReboot"; 218 219 if (0 == getProperty(interface, path, service, property, value)) 220 { 221 // return value is a variant, autoreboot policy is boolean 222 autoReboot = std::get<bool>(value); 223 } 224 } 225 226 return autoReboot; 227 } 228 229 /** @brief Get the running state of the host */ 230 HostRunningState hostRunningState() 231 { 232 // assume not able to get host running state 233 HostRunningState host = HostRunningState::Unknown; 234 235 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress"; 236 237 DBusService service; 238 DBusPath path; 239 240 // find a dbus object and path that implements the interface 241 if (0 == find(interface, path, service)) 242 { 243 DBusValue value; 244 245 // boot progress is implemented as a property 246 constexpr auto property = "BootProgress"; 247 248 if (0 == getProperty(interface, path, service, property, value)) 249 { 250 // return value is a variant, progress is in the vector of strings 251 std::string bootProgress(std::get<std::string>(value)); 252 253 // convert boot progress to host state 254 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot:: 255 server::Progress::ProgressStages; 256 257 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot:: 258 server::Progress::convertProgressStagesFromString(bootProgress); 259 260 if ((stage == BootProgress::SystemInitComplete) || 261 (stage == BootProgress::OSStart) || 262 (stage == BootProgress::OSRunning)) 263 { 264 host = HostRunningState::Started; 265 } 266 else 267 { 268 host = HostRunningState::NotStarted; 269 } 270 } 271 } 272 273 return host; 274 } 275 276 } // namespace dbus 277 278 } // namespace util 279