1 #pragma once 2 3 #include "config.h" 4 5 #include "utils.hpp" 6 7 #include <cereal/cereal.hpp> 8 #include <sdbusplus/bus.hpp> 9 #include <sdeventplus/clock.hpp> 10 #include <sdeventplus/event.hpp> 11 #include <sdeventplus/utility/timer.hpp> 12 #include <xyz/openbmc_project/State/Chassis/server.hpp> 13 #include <xyz/openbmc_project/State/PowerOnHours/server.hpp> 14 15 #include <chrono> 16 #include <filesystem> 17 18 namespace phosphor 19 { 20 namespace state 21 { 22 namespace manager 23 { 24 25 using ChassisInherit = sdbusplus::server::object_t< 26 sdbusplus::server::xyz::openbmc_project::state::Chassis, 27 sdbusplus::server::xyz::openbmc_project::state::PowerOnHours>; 28 namespace sdbusRule = sdbusplus::bus::match::rules; 29 namespace fs = std::filesystem; 30 31 /** @class Chassis 32 * @brief OpenBMC chassis state management implementation. 33 * @details A concrete implementation for xyz.openbmc_project.State.Chassis 34 * DBus API. 35 */ 36 class Chassis : public ChassisInherit 37 { 38 public: 39 /** @brief Constructs Chassis State Manager 40 * 41 * @note This constructor passes 'true' to the base class in order to 42 * defer dbus object registration until we can run 43 * determineInitialState() and set our properties 44 * 45 * @param[in] bus - The Dbus bus object 46 * @param[in] objPath - The Dbus object path 47 * @param[in] id - Chassis id 48 */ Chassis(sdbusplus::bus_t & bus,const char * objPath,size_t id)49 Chassis(sdbusplus::bus_t& bus, const char* objPath, size_t id) : 50 ChassisInherit(bus, objPath, ChassisInherit::action::defer_emit), 51 bus(bus), 52 systemdSignals( 53 bus, 54 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") + 55 sdbusRule::path("/org/freedesktop/systemd1") + 56 sdbusRule::interface("org.freedesktop.systemd1.Manager"), 57 [this](sdbusplus::message_t& m) { sysStateChange(m); }), 58 id(id), 59 pohTimer( __anonacea13680202(auto&) 60 sdeventplus::Event::get_default(), [this](auto&) { pohCallback(); }, __anonacea13680302(auto&) 61 std::chrono::hours{1}, std::chrono::minutes{1}) 62 { 63 utils::subscribeToSystemdSignals(bus); 64 65 createSystemdTargetTable(); 66 67 restoreChassisStateChangeTime(); 68 69 // No default in PDI so start at Good, skip D-Bus signal for now 70 currentPowerStatus(PowerStatus::Good, true); 71 determineInitialState(); 72 73 restorePOHCounter(); // restore POHCounter from persisted file 74 75 // We deferred this until we could get our property correct 76 this->emit_object_added(); 77 } 78 79 /** @brief Set value of RequestedPowerTransition */ 80 Transition requestedPowerTransition(Transition value) override; 81 82 /** @brief Set value of CurrentPowerState */ 83 PowerState currentPowerState(PowerState value) override; 84 85 /** @brief Get value of POHCounter */ 86 using ChassisInherit::pohCounter; 87 88 /** @brief Increment POHCounter if Chassis Power state is ON */ 89 void startPOHCounter(); 90 91 private: 92 /** @brief Create systemd target instance names and mapping table */ 93 void createSystemdTargetTable(); 94 95 /** @brief Determine initial chassis state and set internally */ 96 void determineInitialState(); 97 98 /** @brief Determine status of power into system by examining all the 99 * power-related interfaces of interest 100 */ 101 void determineStatusOfPower(); 102 103 /** @brief Determine status of power provided by an Uninterruptible Power 104 * Supply into the system 105 * 106 * @return True if UPS power is good, false otherwise 107 */ 108 bool determineStatusOfUPSPower(); 109 110 /** @brief Determine status of power provided by the power supply units into 111 * the system 112 * 113 * @return True if PSU power is good, false otherwise 114 */ 115 bool determineStatusOfPSUPower(); 116 117 /** @brief Start the systemd unit requested 118 * 119 * This function calls `StartUnit` on the systemd unit given. 120 * 121 * @param[in] sysdUnit - Systemd unit 122 */ 123 void startUnit(const std::string& sysdUnit); 124 125 /** @brief Restart the systemd unit requested 126 * 127 * This function calls `RestartUnit` on the systemd unit given. 128 * This is useful when needing to restart a service that is already running 129 * 130 * @param[in] sysdUnit - Systemd unit to restart 131 */ 132 void restartUnit(const std::string& sysdUnit); 133 134 /** 135 * @brief Determine if target is active 136 * 137 * This function determines if the target is active and 138 * helps prevent misleading log recorded states. 139 * 140 * @param[in] target - Target string to check on 141 * 142 * @return boolean corresponding to state active 143 **/ 144 bool stateActive(const std::string& target); 145 146 /** @brief Check if systemd state change is relevant to this object 147 * 148 * Instance specific interface to handle the detected systemd state 149 * change 150 * 151 * @param[in] msg - Data associated with subscribed signal 152 * 153 */ 154 int sysStateChange(sdbusplus::message_t& msg); 155 156 /** @brief Persistent sdbusplus DBus connection. */ 157 sdbusplus::bus_t& bus; 158 159 /** @brief Used to subscribe to dbus systemd signals **/ 160 sdbusplus::bus::match_t systemdSignals; 161 162 /** @brief Watch for any changes to UPS properties **/ 163 std::unique_ptr<sdbusplus::bus::match_t> uPowerPropChangeSignal; 164 165 /** @brief Watch for any changes to PowerSystemInputs properties **/ 166 std::unique_ptr<sdbusplus::bus::match_t> powerSysInputsPropChangeSignal; 167 168 /** @brief Chassis id. **/ 169 const size_t id = 0; 170 171 /** @brief Transition state to systemd target mapping table. **/ 172 std::map<Transition, std::string> systemdTargetTable; 173 174 /** @brief Used to Set value of POHCounter */ 175 uint32_t pohCounter(uint32_t value) override; 176 177 /** @brief Used by the timer to update the POHCounter */ 178 void pohCallback(); 179 180 /** @brief Used to restore POHCounter value from persisted file */ 181 void restorePOHCounter(); 182 183 /** @brief Serialize and persist requested POH counter. 184 * 185 * @return fs::path - pathname of persisted requested POH counter. 186 */ 187 fs::path serializePOH(); 188 189 /** @brief Deserialize a persisted requested POH counter. 190 * 191 * @param[in] retCounter - deserialized POH counter value 192 * 193 * @return bool - true if the deserialization was successful, false 194 * otherwise. 195 */ 196 bool deserializePOH(uint32_t& retCounter); 197 198 /** @brief Sets the LastStateChangeTime property and persists it. */ 199 void setStateChangeTime(); 200 201 /** @brief Serialize the last power state change time. 202 * 203 * Save the time the state changed and the state itself. 204 * The state needs to be saved as well so that during rediscovery 205 * on reboots there's a way to know not to update the time again. 206 */ 207 void serializeStateChangeTime(); 208 209 /** @brief Deserialize the last power state change time. 210 * 211 * @param[out] time - Deserialized time 212 * @param[out] state - Deserialized power state 213 * 214 * @return bool - true if successful, false otherwise. 215 */ 216 bool deserializeStateChangeTime(uint64_t& time, PowerState& state); 217 218 /** @brief Restores the power state change time. 219 * 220 * The time is loaded into the LastStateChangeTime D-Bus property. 221 * On the very first start after this code has been applied but 222 * before the state has changed, the LastStateChangeTime value 223 * will be zero. 224 */ 225 void restoreChassisStateChangeTime(); 226 227 /** @brief Timer used for tracking power on hours */ 228 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pohTimer; 229 230 /** @brief Function to check for a standby voltage regulator fault 231 * 232 * Determine if a standby voltage regulator fault was detected and 233 * return true or false accordingly. 234 * 235 * @return true if fault detected, else false 236 */ 237 static bool standbyVoltageRegulatorFault(); 238 239 /** @brief Process UPS property changes 240 * 241 * Instance specific interface to monitor for changes to the UPS 242 * properties which may impact CurrentPowerStatus 243 * 244 * @param[in] msg - Data associated with subscribed signal 245 * 246 */ 247 void uPowerChangeEvent(sdbusplus::message_t& msg); 248 249 /** @brief Process PowerSystemInputs property changes 250 * 251 * Instance specific interface to monitor for changes to the 252 * PowerSystemInputs properties which may impact CurrentPowerStatus 253 * 254 * @param[in] msg - Data associated with subscribed signal 255 * 256 */ 257 void powerSysInputsChangeEvent(sdbusplus::message_t& msg); 258 }; 259 260 } // namespace manager 261 } // namespace state 262 } // namespace phosphor 263