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 */ BMC(sdbusplus::bus_t & bus,const char * objPath)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 timeSyncSignal(std::make_unique<decltype(timeSyncSignal)::element_type>( 49 bus, 50 sdbusRule::propertiesChanged( 51 "/org/freedesktop/systemd1/unit/time_2dsync_2etarget", 52 "org.freedesktop.systemd1.Unit"), __anonbe750f0c0202(sdbusplus::message_t& m) 53 [this](sdbusplus::message_t& m) { 54 std::string interface; 55 std::unordered_map<std::string, std::variant<std::string>> 56 propertyChanged; 57 m.read(interface, propertyChanged); 58 59 for (const auto& [key, value] : propertyChanged) 60 { 61 if (key == "ActiveState" && 62 std::holds_alternative<std::string>(value) && 63 std::get<std::string>(value) == "active") 64 { 65 updateLastRebootTime(); 66 timeSyncSignal.reset(); 67 } 68 } 69 })) 70 { 71 utils::subscribeToSystemdSignals(bus); 72 discoverInitialState(); 73 discoverLastRebootCause(); 74 updateLastRebootTime(); 75 76 this->emit_object_added(); 77 }; 78 79 /** @brief Set value of BMCTransition **/ 80 Transition requestedBMCTransition(Transition value) override; 81 82 /** @brief Set value of CurrentBMCState **/ 83 BMCState currentBMCState(BMCState value) override; 84 85 /** @brief Returns the last time the BMC was rebooted 86 * 87 * @details Uses uptime information to determine when 88 * the BMC was last rebooted. 89 * 90 * @return uint64_t - Epoch time, in milliseconds, of the 91 * last reboot. 92 */ 93 uint64_t lastRebootTime() const override; 94 95 /** @brief Set value of LastRebootCause **/ 96 RebootCause lastRebootCause(RebootCause value) override; 97 98 private: 99 /** 100 * @brief Retrieve input systemd unit state 101 **/ 102 std::string getUnitState(const std::string& unitToCheck); 103 /** 104 * @brief discover the state of the bmc 105 **/ 106 void discoverInitialState(); 107 108 /** @brief Execute the transition request 109 * 110 * @param[in] tranReq - Transition requested 111 */ 112 void executeTransition(Transition tranReq); 113 114 /** @brief Callback function on bmc state change 115 * 116 * Check if the state is relevant to the BMC and if so, update 117 * corresponding BMC object's state 118 * 119 * @param[in] msg - Data associated with subscribed signal 120 * 121 */ 122 int bmcStateChange(sdbusplus::message_t& msg); 123 124 /** @brief Persistent sdbusplus DBus bus connection. **/ 125 sdbusplus::bus_t& bus; 126 127 /** @brief Used to subscribe to dbus system state changes **/ 128 std::unique_ptr<sdbusplus::bus::match_t> stateSignal; 129 130 /** @brief Used to subscribe to timesync **/ 131 std::unique_ptr<sdbusplus::bus::match_t> timeSyncSignal; 132 133 /** 134 * @brief discover the last reboot cause of the bmc 135 **/ 136 void discoverLastRebootCause(); 137 138 /** 139 * @brief update the last reboot time of the bmc 140 **/ 141 void updateLastRebootTime(); 142 143 /** 144 * @brief the lastRebootTime calculated at startup. 145 **/ 146 uint64_t rebootTime; 147 }; 148 149 } // namespace manager 150 } // namespace state 151 } // namespace phosphor 152