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 #include <functional> 17 18 namespace phosphor 19 { 20 namespace state 21 { 22 namespace manager 23 { 24 25 using ChassisInherit = sdbusplus::server::object::object< 26 sdbusplus::xyz::openbmc_project::State::server::Chassis, 27 sdbusplus::xyz::openbmc_project::State::server::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 */ 49 Chassis(sdbusplus::bus::bus& 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 std::bind(std::mem_fn(&Chassis::sysStateChange), this, 58 std::placeholders::_1)), 59 id(id), pohTimer(sdeventplus::Event::get_default(), 60 std::bind(&Chassis::pohCallback, this), 61 std::chrono::hours{1}, std::chrono::minutes{1}) 62 { 63 subscribeToSystemdSignals(); 64 65 createSystemdTargetTable(); 66 67 restoreChassisStateChangeTime(); 68 69 determineInitialState(); 70 71 restorePOHCounter(); // restore POHCounter from persisted file 72 73 // We deferred this until we could get our property correct 74 this->emit_object_added(); 75 } 76 77 /** @brief Set value of RequestedPowerTransition */ 78 Transition requestedPowerTransition(Transition value) override; 79 80 /** @brief Set value of CurrentPowerState */ 81 PowerState currentPowerState(PowerState value) override; 82 83 /** @brief Get value of POHCounter */ 84 using ChassisInherit::pohCounter; 85 86 /** @brief Increment POHCounter if Chassis Power state is ON */ 87 void startPOHCounter(); 88 89 private: 90 /** @brief Create systemd target instance names and mapping table */ 91 void createSystemdTargetTable(); 92 93 /** @brief Determine initial chassis state and set internally */ 94 void determineInitialState(); 95 96 /** @brief Determine status of power into system by examining all the 97 * power-related interfaces of interest 98 */ 99 void determineStatusOfPower(); 100 101 /** @brief Determine status of power provided by an Uninterruptible Power 102 * Supply into the system 103 */ 104 void determineStatusOfUPSPower(); 105 106 /** @brief Determine status of power provided by the power supply units into 107 * the system 108 */ 109 void determineStatusOfPSUPower(); 110 111 /** 112 * @brief subscribe to the systemd signals 113 * 114 * This object needs to capture when it's systemd targets complete 115 * so it can keep it's state updated 116 * 117 **/ 118 void subscribeToSystemdSignals(); 119 120 /** @brief Start the systemd unit requested 121 * 122 * This function calls `StartUnit` on the systemd unit given. 123 * 124 * @param[in] sysdUnit - Systemd unit 125 */ 126 void startUnit(const std::string& sysdUnit); 127 128 /** 129 * @brief Determine if target is active 130 * 131 * This function determines if the target is active and 132 * helps prevent misleading log recorded states. 133 * 134 * @param[in] target - Target string to check on 135 * 136 * @return boolean corresponding to state active 137 **/ 138 bool stateActive(const std::string& target); 139 140 /** @brief Check if systemd state change is relevant to this object 141 * 142 * Instance specific interface to handle the detected systemd state 143 * change 144 * 145 * @param[in] msg - Data associated with subscribed signal 146 * 147 */ 148 int sysStateChange(sdbusplus::message::message& msg); 149 150 /** @brief Persistent sdbusplus DBus connection. */ 151 sdbusplus::bus::bus& bus; 152 153 /** @brief Used to subscribe to dbus systemd signals **/ 154 sdbusplus::bus::match_t systemdSignals; 155 156 /** @brief Watch for any changes to UPS properties **/ 157 std::unique_ptr<sdbusplus::bus::match_t> uPowerPropChangeSignal; 158 159 /** @brief Watch for any changes to PowerSystemInputs properties **/ 160 std::unique_ptr<sdbusplus::bus::match_t> powerSysInputsPropChangeSignal; 161 162 /** @brief Chassis id. **/ 163 const size_t id = 0; 164 165 /** @brief Transition state to systemd target mapping table. **/ 166 std::map<Transition, std::string> systemdTargetTable; 167 168 /** @brief Used to Set value of POHCounter */ 169 uint32_t pohCounter(uint32_t value) override; 170 171 /** @brief Used by the timer to update the POHCounter */ 172 void pohCallback(); 173 174 /** @brief Used to restore POHCounter value from persisted file */ 175 void restorePOHCounter(); 176 177 /** @brief Serialize and persist requested POH counter. 178 * 179 * @param[in] dir - pathname of file where the serialized POH counter will 180 * be placed. 181 * 182 * @return fs::path - pathname of persisted requested POH counter. 183 */ 184 fs::path 185 serializePOH(const fs::path& dir = fs::path(POH_COUNTER_PERSIST_PATH)); 186 187 /** @brief Deserialize a persisted requested POH counter. 188 * 189 * @param[in] path - pathname of persisted POH counter file 190 * @param[in] retCounter - deserialized POH counter value 191 * 192 * @return bool - true if the deserialization was successful, false 193 * otherwise. 194 */ 195 bool deserializePOH(const fs::path& path, uint32_t& retCounter); 196 197 /** @brief Sets the LastStateChangeTime property and persists it. */ 198 void setStateChangeTime(); 199 200 /** @brief Serialize the last power state change time. 201 * 202 * Save the time the state changed and the state itself. 203 * The state needs to be saved as well so that during rediscovery 204 * on reboots there's a way to know not to update the time again. 205 */ 206 void serializeStateChangeTime(); 207 208 /** @brief Deserialize the last power state change time. 209 * 210 * @param[out] time - Deserialized time 211 * @param[out] state - Deserialized power state 212 * 213 * @return bool - true if successful, false otherwise. 214 */ 215 bool deserializeStateChangeTime(uint64_t& time, PowerState& state); 216 217 /** @brief Restores the power state change time. 218 * 219 * The time is loaded into the LastStateChangeTime D-Bus property. 220 * On the very first start after this code has been applied but 221 * before the state has changed, the LastStateChangeTime value 222 * will be zero. 223 */ 224 void restoreChassisStateChangeTime(); 225 226 /** @brief Timer used for tracking power on hours */ 227 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pohTimer; 228 229 /** @brief Function to check for a standby voltage regulator fault 230 * 231 * Determine if a standby voltage regulator fault was detected and 232 * return true or false accordingly. 233 * 234 * @return true if fault detected, else false 235 */ 236 bool standbyVoltageRegulatorFault(); 237 238 /** @brief Process UPS property changes 239 * 240 * Instance specific interface to monitor for changes to the UPS 241 * properties which may impact CurrentPowerStatus 242 * 243 * @param[in] msg - Data associated with subscribed signal 244 * 245 */ 246 void uPowerChangeEvent(sdbusplus::message::message& msg); 247 248 /** @brief Process PowerSystemInputs property changes 249 * 250 * Instance specific interface to monitor for changes to the 251 * PowerSystemInputs properties which may impact CurrentPowerStatus 252 * 253 * @param[in] msg - Data associated with subscribed signal 254 * 255 */ 256 void powerSysInputsChangeEvent(sdbusplus::message::message& msg); 257 }; 258 259 } // namespace manager 260 } // namespace state 261 } // namespace phosphor 262