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