1 #pragma once 2 3 #include "utils.hpp" 4 #include "xyz/openbmc_project/State/BMC/server.hpp" 5 6 #include <linux/watchdog.h> 7 #include <sys/sysinfo.h> 8 9 #include <sdbusplus/bus.hpp> 10 11 #include <cassert> 12 #include <chrono> 13 14 namespace phosphor 15 { 16 namespace state 17 { 18 namespace manager 19 { 20 21 using BMCInherit = sdbusplus::server::object_t< 22 sdbusplus::server::xyz::openbmc_project::state::BMC>; 23 namespace sdbusRule = sdbusplus::bus::match::rules; 24 25 /** @class BMC 26 * @brief OpenBMC BMC state management implementation. 27 * @details A concrete implementation for xyz.openbmc_project.State.BMC 28 * DBus API. 29 */ 30 class BMC : public BMCInherit 31 { 32 public: 33 /** @brief Constructs BMC State Manager 34 * 35 * @param[in] bus - The Dbus bus object 36 * @param[in] busName - The Dbus name to own 37 * @param[in] objPath - The Dbus object path 38 */ 39 BMC(sdbusplus::bus_t& bus, const char* objPath) : 40 BMCInherit(bus, objPath, BMCInherit::action::defer_emit), bus(bus), 41 stateSignal(std::make_unique<decltype(stateSignal)::element_type>( 42 bus, 43 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") + 44 sdbusRule::path("/org/freedesktop/systemd1") + 45 sdbusRule::interface("org.freedesktop.systemd1.Manager"), 46 [this](sdbusplus::message_t& m) { bmcStateChange(m); })) 47 { 48 utils::subscribeToSystemdSignals(bus); 49 discoverInitialState(); 50 discoverLastRebootCause(); 51 52 using namespace std::chrono; 53 struct sysinfo info; 54 55 auto rc = sysinfo(&info); 56 assert(rc == 0); 57 // Since uptime is in seconds, also get the current time in seconds. 58 auto now = time_point_cast<seconds>(system_clock::now()); 59 auto rebootTimeTs = now - seconds(info.uptime); 60 rebootTime = 61 duration_cast<milliseconds>(rebootTimeTs.time_since_epoch()) 62 .count(); 63 64 this->emit_object_added(); 65 }; 66 67 /** @brief Set value of BMCTransition **/ 68 Transition requestedBMCTransition(Transition value) override; 69 70 /** @brief Set value of CurrentBMCState **/ 71 BMCState currentBMCState(BMCState value) override; 72 73 /** @brief Returns the last time the BMC was rebooted 74 * 75 * @details Uses uptime information to determine when 76 * the BMC was last rebooted. 77 * 78 * @return uint64_t - Epoch time, in milliseconds, of the 79 * last reboot. 80 */ 81 uint64_t lastRebootTime() const override; 82 83 /** @brief Set value of LastRebootCause **/ 84 RebootCause lastRebootCause(RebootCause value) override; 85 86 private: 87 /** 88 * @brief Retrieve input systemd unit state 89 **/ 90 std::string getUnitState(const std::string& unitToCheck); 91 /** 92 * @brief discover the state of the bmc 93 **/ 94 void discoverInitialState(); 95 96 /** @brief Execute the transition request 97 * 98 * @param[in] tranReq - Transition requested 99 */ 100 void executeTransition(Transition tranReq); 101 102 /** @brief Callback function on bmc state change 103 * 104 * Check if the state is relevant to the BMC and if so, update 105 * corresponding BMC object's state 106 * 107 * @param[in] msg - Data associated with subscribed signal 108 * 109 */ 110 int bmcStateChange(sdbusplus::message_t& msg); 111 112 /** @brief Persistent sdbusplus DBus bus connection. **/ 113 sdbusplus::bus_t& bus; 114 115 /** @brief Used to subscribe to dbus system state changes **/ 116 std::unique_ptr<sdbusplus::bus::match_t> stateSignal; 117 118 /** 119 * @brief discover the last reboot cause of the bmc 120 **/ 121 void discoverLastRebootCause(); 122 123 /** 124 * @brief the lastRebootTime calcuated at startup. 125 **/ 126 uint64_t rebootTime; 127 }; 128 129 } // namespace manager 130 } // namespace state 131 } // namespace phosphor 132