Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 1 | #include <util/dbus.hpp> |
| 2 | #include <util/trace.hpp> |
Ben Tyner | fe2c50d | 2021-07-23 13:38:53 -0500 | [diff] [blame] | 3 | #include <xyz/openbmc_project/State/Boot/Progress/server.hpp> |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 4 | |
Patrick Williams | 710101c | 2024-02-13 21:37:47 -0600 | [diff] [blame] | 5 | #include <format> |
| 6 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 7 | namespace util |
| 8 | { |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 9 | namespace dbus |
| 10 | { |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 11 | //------------------------------------------------------------------------------ |
| 12 | |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 13 | constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper"; |
| 14 | constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper"; |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 15 | constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper"; |
| 16 | |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 17 | constexpr uint8_t terminusIdZero = 0; |
| 18 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 19 | /** @brief Find the path and service that implements the given interface */ |
| 20 | int find(const std::string& i_interface, std::string& o_path, |
| 21 | std::string& o_service) |
| 22 | { |
| 23 | int rc = 1; // assume not success |
| 24 | |
| 25 | auto bus = sdbusplus::bus::new_default(); |
| 26 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 27 | try |
| 28 | { |
Ben Tyner | 659e65c | 2021-07-21 09:49:35 -0500 | [diff] [blame] | 29 | constexpr auto function = "GetSubTree"; |
| 30 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 31 | auto method = bus.new_method_call(objectMapperService, objectMapperPath, |
| 32 | objectMapperInterface, function); |
| 33 | |
| 34 | // Search the entire dbus tree for the specified interface |
| 35 | method.append(std::string{"/"}, 0, |
| 36 | std::vector<std::string>{i_interface}); |
| 37 | |
| 38 | auto reply = bus.call(method); |
| 39 | |
| 40 | DBusSubTree response; |
| 41 | reply.read(response); |
| 42 | |
| 43 | if (!response.empty()) |
| 44 | { |
| 45 | // Response is a map of object paths to a map of service, interfaces |
| 46 | auto object = *(response.begin()); |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 47 | o_path = object.first; // return path |
| 48 | o_service = object.second.begin()->first; // return service |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 49 | |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 50 | rc = 0; // success |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 51 | } |
| 52 | } |
| 53 | catch (const sdbusplus::exception::SdBusError& e) |
| 54 | { |
| 55 | trace::err("util::dbus::find exception"); |
| 56 | std::string traceMsg = std::string(e.what()); |
| 57 | trace::err(traceMsg.c_str()); |
| 58 | } |
| 59 | |
| 60 | return rc; |
| 61 | } |
| 62 | |
| 63 | /** @brief Find the service that implements the given object and interface */ |
| 64 | int findService(const std::string& i_interface, const std::string& i_path, |
| 65 | std::string& o_service) |
| 66 | { |
| 67 | int rc = 1; // assume not success |
| 68 | |
| 69 | auto bus = sdbusplus::bus::new_default(); |
| 70 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 71 | try |
| 72 | { |
Ben Tyner | 659e65c | 2021-07-21 09:49:35 -0500 | [diff] [blame] | 73 | constexpr auto function = "GetObject"; |
| 74 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 75 | auto method = bus.new_method_call(objectMapperService, objectMapperPath, |
| 76 | objectMapperInterface, function); |
| 77 | |
| 78 | // Find services that implement the object path, constrain the search |
| 79 | // to the given interface. |
| 80 | method.append(i_path, std::vector<std::string>{i_interface}); |
| 81 | |
| 82 | auto reply = bus.call(method); |
| 83 | |
| 84 | // response is a map of service names to their interfaces |
| 85 | std::map<DBusService, DBusInterfaceList> response; |
| 86 | reply.read(response); |
| 87 | |
| 88 | if (!response.empty()) |
| 89 | { |
| 90 | // return the service |
| 91 | o_service = response.begin()->first; |
| 92 | |
| 93 | rc = 0; // success |
| 94 | } |
| 95 | } |
| 96 | catch (const sdbusplus::exception::SdBusError& e) |
| 97 | { |
| 98 | trace::err("util::dbus::map exception"); |
| 99 | std::string traceMsg = std::string(e.what()); |
| 100 | trace::err(traceMsg.c_str()); |
| 101 | } |
| 102 | |
| 103 | return rc; |
| 104 | } |
| 105 | |
| 106 | /** @brief Read a property from a dbus object interface */ |
| 107 | int getProperty(const std::string& i_interface, const std::string& i_path, |
| 108 | const std::string& i_service, const std::string& i_property, |
| 109 | DBusValue& o_response) |
| 110 | { |
| 111 | int rc = 1; // assume not success |
| 112 | |
| 113 | auto bus = sdbusplus::bus::new_default(); |
| 114 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 115 | try |
| 116 | { |
Ben Tyner | 659e65c | 2021-07-21 09:49:35 -0500 | [diff] [blame] | 117 | constexpr auto interface = "org.freedesktop.DBus.Properties"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 118 | constexpr auto function = "Get"; |
Ben Tyner | 659e65c | 2021-07-21 09:49:35 -0500 | [diff] [blame] | 119 | |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 120 | // calling the get property method |
| 121 | auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(), |
| 122 | interface, function); |
| 123 | |
| 124 | method.append(i_interface, i_property); |
| 125 | auto reply = bus.call(method); |
| 126 | |
| 127 | // returning the property value |
| 128 | reply.read(o_response); |
| 129 | |
| 130 | rc = 0; // success |
| 131 | } |
| 132 | catch (const sdbusplus::exception::SdBusError& e) |
| 133 | { |
| 134 | trace::err("util::dbus::getProperty exception"); |
| 135 | std::string traceMsg = std::string(e.what()); |
| 136 | trace::err(traceMsg.c_str()); |
| 137 | } |
| 138 | |
| 139 | return rc; |
| 140 | } |
| 141 | |
| 142 | /** @brief Get the IBM compatible names defined for this system */ |
| 143 | std::vector<std::string> systemNames() |
| 144 | { |
| 145 | std::vector<std::string> names; |
| 146 | |
| 147 | constexpr auto interface = |
| 148 | "xyz.openbmc_project.Configuration.IBMCompatibleSystem"; |
| 149 | |
| 150 | DBusService service; |
| 151 | DBusPath path; |
| 152 | |
| 153 | // find a dbus object and path that implements the interface |
| 154 | if (0 == find(interface, path, service)) |
| 155 | { |
| 156 | DBusValue value; |
| 157 | |
| 158 | // compatible system names are implemented as a property |
| 159 | constexpr auto property = "Names"; |
| 160 | |
| 161 | if (0 == getProperty(interface, path, service, property, value)) |
| 162 | { |
| 163 | // return value is a variant, names are in the vector |
| 164 | names = std::get<std::vector<std::string>>(value); |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | return names; |
| 169 | } |
| 170 | |
Ben Tyner | 9306716 | 2021-07-23 10:39:30 -0500 | [diff] [blame] | 171 | /** @brief Transition the host state */ |
| 172 | void transitionHost(const HostState i_hostState) |
| 173 | { |
| 174 | try |
| 175 | { |
| 176 | // We will be transitioning host by starting appropriate dbus target |
| 177 | std::string target = "obmc-host-quiesce@0.target"; // quiesce is default |
| 178 | |
| 179 | // crash (mpipl) mode state requested |
| 180 | if (HostState::Crash == i_hostState) |
| 181 | { |
| 182 | target = "obmc-host-crash@0.target"; |
| 183 | } |
| 184 | |
Andrew Geissler | 1ff926e | 2023-01-26 08:14:22 -0700 | [diff] [blame] | 185 | // If the system is powering off for any reason (ex. we hit a PHYP TI |
| 186 | // in the graceful power off path), then we want to call the immediate |
| 187 | // power off target |
| 188 | if (hostRunningState() == HostRunningState::Stopping) |
| 189 | { |
| 190 | trace::inf("system is powering off so no dump will be requested"); |
| 191 | target = "obmc-chassis-hard-poweroff@0.target"; |
| 192 | } |
| 193 | |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 194 | auto bus = sdbusplus::bus::new_system(); |
Ben Tyner | 9306716 | 2021-07-23 10:39:30 -0500 | [diff] [blame] | 195 | auto method = bus.new_method_call( |
| 196 | "org.freedesktop.systemd1", "/org/freedesktop/systemd1", |
| 197 | "org.freedesktop.systemd1.Manager", "StartUnit"); |
| 198 | |
| 199 | method.append(target); // target unit to start |
| 200 | method.append("replace"); // mode = replace conflicting queued jobs |
| 201 | |
| 202 | bus.call_noreply(method); // start the service |
| 203 | } |
| 204 | catch (const sdbusplus::exception::SdBusError& e) |
| 205 | { |
| 206 | trace::err("util::dbus::transitionHost exception"); |
| 207 | std::string traceMsg = std::string(e.what()); |
| 208 | trace::err(traceMsg.c_str()); |
| 209 | } |
| 210 | } |
| 211 | |
Ben Tyner | 39fcf65 | 2021-10-19 20:38:29 -0500 | [diff] [blame] | 212 | /** @brief Read state of autoRebootEnabled property via dbus */ |
Ben Tyner | ffb4867 | 2021-07-23 12:29:03 -0500 | [diff] [blame] | 213 | bool autoRebootEnabled() |
| 214 | { |
Ben Tyner | 39fcf65 | 2021-10-19 20:38:29 -0500 | [diff] [blame] | 215 | // Assume true in case autoRebootEnbabled property is not available |
| 216 | bool autoReboot = true; |
Ben Tyner | ffb4867 | 2021-07-23 12:29:03 -0500 | [diff] [blame] | 217 | |
| 218 | constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy"; |
| 219 | |
Ben Tyner | 39fcf65 | 2021-10-19 20:38:29 -0500 | [diff] [blame] | 220 | DBusService service; // will find this |
| 221 | DBusPath path; // will find this |
Ben Tyner | ffb4867 | 2021-07-23 12:29:03 -0500 | [diff] [blame] | 222 | |
| 223 | // find a dbus object and path that implements the interface |
| 224 | if (0 == find(interface, path, service)) |
| 225 | { |
| 226 | DBusValue value; |
| 227 | |
| 228 | // autoreboot policy is implemented as a property |
| 229 | constexpr auto property = "AutoReboot"; |
| 230 | |
| 231 | if (0 == getProperty(interface, path, service, property, value)) |
| 232 | { |
| 233 | // return value is a variant, autoreboot policy is boolean |
| 234 | autoReboot = std::get<bool>(value); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | return autoReboot; |
| 239 | } |
| 240 | |
Ben Tyner | fe2c50d | 2021-07-23 13:38:53 -0500 | [diff] [blame] | 241 | /** @brief Get the running state of the host */ |
| 242 | HostRunningState hostRunningState() |
| 243 | { |
| 244 | // assume not able to get host running state |
| 245 | HostRunningState host = HostRunningState::Unknown; |
| 246 | |
| 247 | constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress"; |
| 248 | |
| 249 | DBusService service; |
| 250 | DBusPath path; |
| 251 | |
| 252 | // find a dbus object and path that implements the interface |
| 253 | if (0 == find(interface, path, service)) |
| 254 | { |
| 255 | DBusValue value; |
| 256 | |
| 257 | // boot progress is implemented as a property |
| 258 | constexpr auto property = "BootProgress"; |
| 259 | |
| 260 | if (0 == getProperty(interface, path, service, property, value)) |
| 261 | { |
| 262 | // return value is a variant, progress is in the vector of strings |
| 263 | std::string bootProgress(std::get<std::string>(value)); |
| 264 | |
| 265 | // convert boot progress to host state |
| 266 | using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot:: |
| 267 | server::Progress::ProgressStages; |
| 268 | |
| 269 | BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot:: |
| 270 | server::Progress::convertProgressStagesFromString(bootProgress); |
| 271 | |
| 272 | if ((stage == BootProgress::SystemInitComplete) || |
Ben Tyner | fe2c50d | 2021-07-23 13:38:53 -0500 | [diff] [blame] | 273 | (stage == BootProgress::OSRunning)) |
| 274 | { |
| 275 | host = HostRunningState::Started; |
| 276 | } |
| 277 | else |
| 278 | { |
| 279 | host = HostRunningState::NotStarted; |
| 280 | } |
| 281 | } |
| 282 | } |
| 283 | |
Andrew Geissler | 1ff926e | 2023-01-26 08:14:22 -0700 | [diff] [blame] | 284 | // See if host in process of powering off when we get NotStarted |
| 285 | if (host == HostRunningState::NotStarted) |
| 286 | { |
| 287 | constexpr auto hostStateInterface = "xyz.openbmc_project.State.Host"; |
| 288 | if (0 == find(hostStateInterface, path, service)) |
| 289 | { |
| 290 | DBusValue value; |
| 291 | |
| 292 | // current host state is implemented as a property |
| 293 | constexpr auto stateProperty = "CurrentHostState"; |
| 294 | |
| 295 | if (0 == getProperty(hostStateInterface, path, service, |
| 296 | stateProperty, value)) |
| 297 | { |
| 298 | // return value is a variant, host state is in the vector of |
| 299 | // strings |
| 300 | std::string hostState(std::get<std::string>(value)); |
| 301 | if (hostState == "xyz.openbmc_project.State.Host.HostState." |
| 302 | "TransitioningToOff") |
| 303 | { |
| 304 | host = HostRunningState::Stopping; |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | } |
| 309 | |
Ben Tyner | fe2c50d | 2021-07-23 13:38:53 -0500 | [diff] [blame] | 310 | return host; |
| 311 | } |
| 312 | |
Ben Tyner | 39fcf65 | 2021-10-19 20:38:29 -0500 | [diff] [blame] | 313 | /** @brief Read state of dumpPolicyEnabled property via dbus */ |
| 314 | bool dumpPolicyEnabled() |
| 315 | { |
| 316 | // Assume true In case dumpPolicyEnabled property is not available |
| 317 | bool dumpPolicyEnabled = true; |
| 318 | |
| 319 | constexpr auto interface = "xyz.openbmc_project.Object.Enable"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 320 | constexpr auto path = "/xyz/openbmc_project/dump/system_dump_policy"; |
Ben Tyner | 39fcf65 | 2021-10-19 20:38:29 -0500 | [diff] [blame] | 321 | |
| 322 | DBusService service; // will find this |
| 323 | |
| 324 | // find a dbus object and path that implements the interface |
| 325 | if (0 == findService(interface, path, service)) |
| 326 | { |
| 327 | DBusValue value; |
| 328 | |
| 329 | // autoreboot policy is implemented as a property |
| 330 | constexpr auto property = "Enabled"; |
| 331 | |
| 332 | if (0 == getProperty(interface, path, service, property, value)) |
| 333 | { |
| 334 | // return value is a variant, dump policy enabled is a boolean |
| 335 | dumpPolicyEnabled = std::get<bool>(value); |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | return dumpPolicyEnabled; |
| 340 | } |
| 341 | |
Ben Tyner | 1315968 | 2022-02-16 14:55:38 -0600 | [diff] [blame] | 342 | /** @brief Create a PEL */ |
| 343 | uint32_t createPel(const std::string& i_message, const std::string& i_severity, |
| 344 | std::map<std::string, std::string>& io_additional, |
| 345 | const std::vector<util::FFDCTuple>& i_ffdc) |
| 346 | { |
| 347 | // CreatePELWithFFDCFiles returns plid |
| 348 | int plid = 0; |
| 349 | |
| 350 | // Sdbus call specifics |
| 351 | constexpr auto interface = "org.open_power.Logging.PEL"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 352 | constexpr auto path = "/xyz/openbmc_project/logging"; |
Ben Tyner | 1315968 | 2022-02-16 14:55:38 -0600 | [diff] [blame] | 353 | |
| 354 | // we need to find the service implementing the interface |
| 355 | util::dbus::DBusService service; |
| 356 | |
| 357 | if (0 == findService(interface, path, service)) |
| 358 | { |
| 359 | try |
| 360 | { |
| 361 | constexpr auto function = "CreatePELWithFFDCFiles"; |
| 362 | |
| 363 | // The "Create" method requires manually adding the process ID. |
| 364 | io_additional["_PID"] = std::to_string(getpid()); |
| 365 | |
| 366 | // create dbus method |
| 367 | auto bus = sdbusplus::bus::new_system(); |
Patrick Williams | e212fb0 | 2022-07-22 19:26:57 -0500 | [diff] [blame] | 368 | sdbusplus::message_t method = |
Ben Tyner | 1315968 | 2022-02-16 14:55:38 -0600 | [diff] [blame] | 369 | bus.new_method_call(service.c_str(), path, interface, function); |
| 370 | |
| 371 | // append additional dbus call paramaters |
| 372 | method.append(i_message, i_severity, io_additional, i_ffdc); |
| 373 | |
| 374 | // using system dbus |
| 375 | auto response = bus.call(method); |
| 376 | |
| 377 | // reply will be tuple containing bmc log id, platform log id |
| 378 | std::tuple<uint32_t, uint32_t> reply = {0, 0}; |
| 379 | |
| 380 | // parse dbus response into reply |
| 381 | response.read(reply); |
| 382 | plid = std::get<1>(reply); // platform log id is tuple "second" |
| 383 | } |
| 384 | catch (const sdbusplus::exception::SdBusError& e) |
| 385 | { |
| 386 | trace::err("createPel exception"); |
| 387 | trace::err(e.what()); |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | return plid; // platform log id or 0 |
| 392 | } |
| 393 | |
Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 394 | MachineType getMachineType() |
| 395 | { |
| 396 | // default to Rainier 2S4U |
| 397 | MachineType machineType = MachineType::Rainier_2S4U; |
| 398 | |
| 399 | // The return value of the dbus operation is a vector of 4 uint8_ts |
| 400 | std::vector<uint8_t> ids; |
| 401 | |
| 402 | constexpr auto interface = "com.ibm.ipzvpd.VSBP"; |
| 403 | |
| 404 | DBusService service; |
| 405 | DBusPath path; |
| 406 | |
| 407 | if (0 == find(interface, path, service)) |
| 408 | { |
| 409 | DBusValue value; |
| 410 | |
| 411 | // Machine ID is given from the "IM" keyword |
| 412 | constexpr auto property = "IM"; |
| 413 | |
| 414 | if (0 == getProperty(interface, path, service, property, value)) |
| 415 | { |
| 416 | // return value is a variant, ID value is a vector of 4 uint8_ts |
| 417 | ids = std::get<std::vector<uint8_t>>(value); |
| 418 | |
| 419 | // Convert the returned ID value to a hex string to determine |
| 420 | // machine type. The hex values corresponding to the machine type |
| 421 | // are defined in /openbmc/openpower-vpd-parser/const.hpp |
| 422 | // RAINIER_2S4U == 0x50001000 |
| 423 | // RAINIER_2S2U == 0x50001001 |
| 424 | // RAINIER_1S4U == 0x50001002 |
| 425 | // RAINIER_1S2U == 0x50001003 |
| 426 | // EVEREST == 0x50003000 |
Zane Shelley | a7dc66b | 2023-11-06 14:01:18 -0600 | [diff] [blame] | 427 | // BONNELL == 0x50004000 |
Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 428 | try |
| 429 | { |
| 430 | // Format the vector into a single hex string to compare to. |
Patrick Williams | 710101c | 2024-02-13 21:37:47 -0600 | [diff] [blame] | 431 | std::string hexId = std::format("0x{:02x}{:02x}{:02x}{:02x}", |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 432 | ids.at(0), ids.at(1), ids.at(2), |
| 433 | ids.at(3)); |
Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 434 | |
| 435 | std::map<std::string, MachineType> typeMap = { |
| 436 | {"0x50001000", MachineType::Rainier_2S4U}, |
| 437 | {"0x50001001", MachineType::Rainier_2S2U}, |
| 438 | {"0x50001002", MachineType::Rainier_1S4U}, |
| 439 | {"0x50001003", MachineType::Rainier_1S2U}, |
| 440 | {"0x50003000", MachineType::Everest}, |
Zane Shelley | a7dc66b | 2023-11-06 14:01:18 -0600 | [diff] [blame] | 441 | {"0x50004000", MachineType::Bonnell}, |
Caleb Palmer | 626270a | 2022-02-21 11:05:08 -0600 | [diff] [blame] | 442 | }; |
| 443 | |
| 444 | machineType = typeMap.at(hexId); |
| 445 | } |
| 446 | catch (const std::out_of_range& e) |
| 447 | { |
| 448 | trace::err("Out of range exception caught from returned " |
| 449 | "machine ID."); |
| 450 | for (const auto& id : ids) |
| 451 | { |
| 452 | trace::err("Returned Machine ID value: 0x%x", id); |
| 453 | } |
| 454 | throw; |
| 455 | } |
| 456 | } |
| 457 | } |
| 458 | else |
| 459 | { |
| 460 | throw std::invalid_argument( |
| 461 | "Unable to find dbus service to get machine type."); |
| 462 | } |
| 463 | |
| 464 | return machineType; |
| 465 | } |
| 466 | |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 467 | /** @brief Get list of state effecter PDRs */ |
| 468 | bool getStateEffecterPdrs(std::vector<std::vector<uint8_t>>& pdrList, |
| 469 | uint16_t stateSetId) |
| 470 | { |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 471 | constexpr auto service = "xyz.openbmc_project.PLDM"; |
| 472 | constexpr auto path = "/xyz/openbmc_project/pldm"; |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 473 | constexpr auto interface = "xyz.openbmc_project.PLDM.PDR"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 474 | constexpr auto function = "FindStateEffecterPDR"; |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 475 | |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 476 | constexpr uint16_t PLDM_ENTITY_PROC = 135; |
| 477 | |
| 478 | try |
| 479 | { |
| 480 | // create dbus method |
| 481 | auto bus = sdbusplus::bus::new_default(); |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 482 | sdbusplus::message_t method = bus.new_method_call(service, path, |
| 483 | interface, function); |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 484 | |
| 485 | // append additional method data |
| 486 | method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId); |
| 487 | |
| 488 | // request PDRs |
| 489 | auto reply = bus.call(method); |
| 490 | reply.read(pdrList); |
| 491 | } |
| 492 | catch (const sdbusplus::exception_t& e) |
| 493 | { |
| 494 | trace::err("failed to find state effecter PDRs"); |
| 495 | trace::err(e.what()); |
| 496 | return false; |
| 497 | } |
| 498 | |
| 499 | return true; |
| 500 | } |
| 501 | |
| 502 | /** @brief Get list of state sensor PDRs */ |
| 503 | bool getStateSensorPdrs(std::vector<std::vector<uint8_t>>& pdrList, |
| 504 | uint16_t stateSetId) |
| 505 | { |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 506 | constexpr auto service = "xyz.openbmc_project.PLDM"; |
| 507 | constexpr auto path = "/xyz/openbmc_project/pldm"; |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 508 | constexpr auto interface = "xyz.openbmc_project.PLDM.PDR"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 509 | constexpr auto function = "FindStateSensorPDR"; |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 510 | |
| 511 | constexpr uint16_t PLDM_ENTITY_PROC = 135; |
| 512 | |
| 513 | try |
| 514 | { |
| 515 | // create dbus method |
| 516 | auto bus = sdbusplus::bus::new_default(); |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 517 | sdbusplus::message_t method = bus.new_method_call(service, path, |
| 518 | interface, function); |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 519 | |
| 520 | // append additional method data |
| 521 | method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId); |
| 522 | |
| 523 | // request PDRs |
| 524 | auto reply = bus.call(method); |
| 525 | reply.read(pdrList); |
| 526 | } |
| 527 | catch (const sdbusplus::exception_t& e) |
| 528 | { |
| 529 | trace::err("failed to find state sensor PDRs"); |
| 530 | trace::err(e.what()); |
| 531 | return false; |
| 532 | } |
| 533 | |
| 534 | return true; |
| 535 | } |
| 536 | |
| 537 | /** @brief Get MCTP instance associated with endpoint */ |
| 538 | bool getMctpInstance(uint8_t& mctpInstance, uint8_t Eid) |
| 539 | { |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 540 | constexpr auto service = "xyz.openbmc_project.PLDM"; |
| 541 | constexpr auto path = "/xyz/openbmc_project/pldm"; |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 542 | constexpr auto interface = "xyz.openbmc_project.PLDM.Requester"; |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 543 | constexpr auto function = "GetInstanceId"; |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 544 | |
| 545 | try |
| 546 | { |
| 547 | // create dbus method |
| 548 | auto bus = sdbusplus::bus::new_default(); |
Patrick Williams | 27dd636 | 2023-05-10 07:51:20 -0500 | [diff] [blame] | 549 | sdbusplus::message_t method = bus.new_method_call(service, path, |
| 550 | interface, function); |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 551 | |
| 552 | // append endpoint ID |
| 553 | method.append(Eid); |
| 554 | |
| 555 | // request MCTP instance ID |
| 556 | auto reply = bus.call(method); |
| 557 | reply.read(mctpInstance); |
| 558 | } |
| 559 | catch (const sdbusplus::exception_t& e) |
| 560 | { |
| 561 | trace::err("get MCTP instance exception"); |
| 562 | trace::err(e.what()); |
| 563 | return false; |
| 564 | } |
| 565 | |
| 566 | return true; |
| 567 | } |
| 568 | |
Ben Tyner | 2b26b2b | 2022-12-15 15:42:02 -0600 | [diff] [blame] | 569 | /** @brief Determine if power fault was detected */ |
| 570 | bool powerFault() |
| 571 | { |
| 572 | // power fault based on pgood property |
| 573 | int32_t pgood = 0; // assume fault or unknown |
| 574 | |
| 575 | constexpr auto interface = "org.openbmc.control.Power"; |
| 576 | |
| 577 | DBusService service; |
| 578 | DBusPath path; |
| 579 | |
| 580 | // find a dbus service and object path that implements the interface |
| 581 | if (0 == find(interface, path, service)) |
| 582 | { |
| 583 | DBusValue value; |
| 584 | |
| 585 | // chassis pgood is implemented as a property |
| 586 | constexpr auto property = "pgood"; |
| 587 | |
| 588 | if (0 == getProperty(interface, path, service, property, value)) |
| 589 | { |
| 590 | // return value is a variant, int32 == 1 for pgood OK |
| 591 | pgood = std::get<int32_t>(value); |
| 592 | } |
| 593 | } |
| 594 | |
| 595 | return pgood != 1 ? true : false; // if not pgood then power fault |
| 596 | } |
| 597 | |
Ben Tyner | 88b1009 | 2022-12-14 20:43:50 -0600 | [diff] [blame] | 598 | } // namespace dbus |
Ben Tyner | 324234b | 2021-06-28 17:01:17 -0500 | [diff] [blame] | 599 | } // namespace util |