1a90a31a9SAndrew Geissler #pragma once
2a90a31a9SAndrew Geissler 
3e426b589SAndrew Geissler #include "config.h"
4e426b589SAndrew Geissler 
5e426b589SAndrew Geissler #include "xyz/openbmc_project/State/Chassis/server.hpp"
6e426b589SAndrew Geissler #include "xyz/openbmc_project/State/PowerOnHours/server.hpp"
7e426b589SAndrew Geissler 
8cb781fe1SNagaraju Goruganti #include <cereal/cereal.hpp>
9a90a31a9SAndrew Geissler #include <sdbusplus/bus.hpp>
10d998f82bSWilliam A. Kennington III #include <sdeventplus/clock.hpp>
11d998f82bSWilliam A. Kennington III #include <sdeventplus/event.hpp>
12d998f82bSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp>
13e426b589SAndrew Geissler 
14e426b589SAndrew Geissler #include <chrono>
156ed41eabSPatrick Williams #include <filesystem>
16e426b589SAndrew Geissler #include <functional>
17a90a31a9SAndrew Geissler 
18a90a31a9SAndrew Geissler namespace phosphor
19a90a31a9SAndrew Geissler {
20a90a31a9SAndrew Geissler namespace state
21a90a31a9SAndrew Geissler {
22a90a31a9SAndrew Geissler namespace manager
23a90a31a9SAndrew Geissler {
24a90a31a9SAndrew Geissler 
25*f053e6feSPatrick Williams using ChassisInherit = sdbusplus::server::object_t<
26cb781fe1SNagaraju Goruganti     sdbusplus::xyz::openbmc_project::State::server::Chassis,
27cb781fe1SNagaraju Goruganti     sdbusplus::xyz::openbmc_project::State::server::PowerOnHours>;
288f8ba39fSPatrick Williams namespace sdbusRule = sdbusplus::bus::match::rules;
296ed41eabSPatrick Williams namespace fs = std::filesystem;
308f8ba39fSPatrick Williams 
31a90a31a9SAndrew Geissler /** @class Chassis
32a90a31a9SAndrew Geissler  *  @brief OpenBMC chassis state management implementation.
33a90a31a9SAndrew Geissler  *  @details A concrete implementation for xyz.openbmc_project.State.Chassis
34a90a31a9SAndrew Geissler  *  DBus API.
35a90a31a9SAndrew Geissler  */
368f8ba39fSPatrick Williams class Chassis : public ChassisInherit
37a90a31a9SAndrew Geissler {
38a90a31a9SAndrew Geissler   public:
39a90a31a9SAndrew Geissler     /** @brief Constructs Chassis State Manager
40a90a31a9SAndrew Geissler      *
41dff50ed6SAndrew Geissler      * @note This constructor passes 'true' to the base class in order to
42dff50ed6SAndrew Geissler      *       defer dbus object registration until we can run
43dff50ed6SAndrew Geissler      *       determineInitialState() and set our properties
44dff50ed6SAndrew Geissler      *
45a90a31a9SAndrew Geissler      * @param[in] bus       - The Dbus bus object
46a90a31a9SAndrew Geissler      * @param[in] objPath   - The Dbus object path
4770f36d8eSPotin Lai      * @param[in] id        - Chassis id
48a90a31a9SAndrew Geissler      */
49*f053e6feSPatrick Williams     Chassis(sdbusplus::bus_t& bus, const char* objPath, size_t id) :
5076070747SPatrick Williams         ChassisInherit(bus, objPath, ChassisInherit::action::defer_emit),
5176070747SPatrick Williams         bus(bus),
5258a18013SAndrew Geissler         systemdSignals(
5358a18013SAndrew Geissler             bus,
5458a18013SAndrew Geissler             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
558f8ba39fSPatrick Williams                 sdbusRule::path("/org/freedesktop/systemd1") +
5658a18013SAndrew Geissler                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
5758a18013SAndrew Geissler             std::bind(std::mem_fn(&Chassis::sysStateChange), this,
58d998f82bSWilliam A. Kennington III                       std::placeholders::_1)),
5970f36d8eSPotin Lai         id(id), pohTimer(sdeventplus::Event::get_default(),
6070f36d8eSPotin Lai                          std::bind(&Chassis::pohCallback, this),
6170f36d8eSPotin Lai                          std::chrono::hours{1}, std::chrono::minutes{1})
62dff50ed6SAndrew Geissler     {
630029a5d2SAndrew Geissler         subscribeToSystemdSignals();
640029a5d2SAndrew Geissler 
6570f36d8eSPotin Lai         createSystemdTargetTable();
6670f36d8eSPotin Lai 
679eab9861SMatt Spinler         restoreChassisStateChangeTime();
689eab9861SMatt Spinler 
6977a91831SAndrew Geissler         // No default in PDI so start at Good, skip D-Bus signal for now
7077a91831SAndrew Geissler         currentPowerStatus(PowerStatus::Good, true);
71dff50ed6SAndrew Geissler         determineInitialState();
72dff50ed6SAndrew Geissler 
73cb781fe1SNagaraju Goruganti         restorePOHCounter(); // restore POHCounter from persisted file
74cb781fe1SNagaraju Goruganti 
75dff50ed6SAndrew Geissler         // We deferred this until we could get our property correct
76dff50ed6SAndrew Geissler         this->emit_object_added();
77dff50ed6SAndrew Geissler     }
78dff50ed6SAndrew Geissler 
79a90a31a9SAndrew Geissler     /** @brief Set value of RequestedPowerTransition */
80a90a31a9SAndrew Geissler     Transition requestedPowerTransition(Transition value) override;
81a90a31a9SAndrew Geissler 
82a90a31a9SAndrew Geissler     /** @brief Set value of CurrentPowerState */
83a90a31a9SAndrew Geissler     PowerState currentPowerState(PowerState value) override;
84a90a31a9SAndrew Geissler 
85cb781fe1SNagaraju Goruganti     /** @brief Get value of POHCounter */
8645a1ed71SPatrick Williams     using ChassisInherit::pohCounter;
87cb781fe1SNagaraju Goruganti 
88cb781fe1SNagaraju Goruganti     /** @brief Increment POHCounter if Chassis Power state is ON */
89cb781fe1SNagaraju Goruganti     void startPOHCounter();
90cb781fe1SNagaraju Goruganti 
91a90a31a9SAndrew Geissler   private:
9270f36d8eSPotin Lai     /** @brief Create systemd target instance names and mapping table */
9370f36d8eSPotin Lai     void createSystemdTargetTable();
9470f36d8eSPotin Lai 
950029a5d2SAndrew Geissler     /** @brief Determine initial chassis state and set internally */
960029a5d2SAndrew Geissler     void determineInitialState();
970029a5d2SAndrew Geissler 
98396ed8a5SAdriana Kobylak     /** @brief Determine status of power into system by examining all the
99396ed8a5SAdriana Kobylak      *        power-related interfaces of interest
100396ed8a5SAdriana Kobylak      */
1018b1f8620SAndrew Geissler     void determineStatusOfPower();
1028b1f8620SAndrew Geissler 
103396ed8a5SAdriana Kobylak     /** @brief Determine status of power provided by an Uninterruptible Power
104396ed8a5SAdriana Kobylak      *         Supply into the system
10566aacdc4SAndrew Geissler      *
10666aacdc4SAndrew Geissler      *  @return True if UPS power is good, false otherwise
107396ed8a5SAdriana Kobylak      */
10866aacdc4SAndrew Geissler     bool determineStatusOfUPSPower();
109396ed8a5SAdriana Kobylak 
110396ed8a5SAdriana Kobylak     /** @brief Determine status of power provided by the power supply units into
111396ed8a5SAdriana Kobylak      *         the system
11266aacdc4SAndrew Geissler      *
11366aacdc4SAndrew Geissler      *  @return True if PSU power is good, false otherwise
114396ed8a5SAdriana Kobylak      */
11566aacdc4SAndrew Geissler     bool determineStatusOfPSUPower();
116396ed8a5SAdriana Kobylak 
1170029a5d2SAndrew Geissler     /**
1180029a5d2SAndrew Geissler      * @brief subscribe to the systemd signals
1190029a5d2SAndrew Geissler      *
1200029a5d2SAndrew Geissler      * This object needs to capture when it's systemd targets complete
1210029a5d2SAndrew Geissler      * so it can keep it's state updated
1220029a5d2SAndrew Geissler      *
1230029a5d2SAndrew Geissler      **/
1240029a5d2SAndrew Geissler     void subscribeToSystemdSignals();
1250029a5d2SAndrew Geissler 
126be6efabcSMatthew Barth     /** @brief Start the systemd unit requested
127ce80f24cSAndrew Geissler      *
128be6efabcSMatthew Barth      * This function calls `StartUnit` on the systemd unit given.
129ce80f24cSAndrew Geissler      *
130be6efabcSMatthew Barth      * @param[in] sysdUnit    - Systemd unit
131ce80f24cSAndrew Geissler      */
132be6efabcSMatthew Barth     void startUnit(const std::string& sysdUnit);
133ce80f24cSAndrew Geissler 
13477a91831SAndrew Geissler     /** @brief Restart the systemd unit requested
13577a91831SAndrew Geissler      *
13677a91831SAndrew Geissler      * This function calls `RestartUnit` on the systemd unit given.
13777a91831SAndrew Geissler      * This is useful when needing to restart a service that is already running
13877a91831SAndrew Geissler      *
13977a91831SAndrew Geissler      * @param[in] sysdUnit    - Systemd unit to restart
14077a91831SAndrew Geissler      */
14177a91831SAndrew Geissler     void restartUnit(const std::string& sysdUnit);
14277a91831SAndrew Geissler 
143697474c5SJosh D. King     /**
144697474c5SJosh D. King      * @brief Determine if target is active
145697474c5SJosh D. King      *
146697474c5SJosh D. King      * This function determines if the target is active and
147697474c5SJosh D. King      * helps prevent misleading log recorded states.
148697474c5SJosh D. King      *
149697474c5SJosh D. King      * @param[in] target - Target string to check on
150697474c5SJosh D. King      *
151697474c5SJosh D. King      * @return boolean corresponding to state active
152697474c5SJosh D. King      **/
153697474c5SJosh D. King     bool stateActive(const std::string& target);
154697474c5SJosh D. King 
1550029a5d2SAndrew Geissler     /** @brief Check if systemd state change is relevant to this object
1562ec3a7e9SAndrew Geissler      *
1570029a5d2SAndrew Geissler      * Instance specific interface to handle the detected systemd state
1580029a5d2SAndrew Geissler      * change
1592ec3a7e9SAndrew Geissler      *
1602ec3a7e9SAndrew Geissler      * @param[in]  msg       - Data associated with subscribed signal
1612ec3a7e9SAndrew Geissler      *
1622ec3a7e9SAndrew Geissler      */
163*f053e6feSPatrick Williams     int sysStateChange(sdbusplus::message_t& msg);
1642ec3a7e9SAndrew Geissler 
165a90a31a9SAndrew Geissler     /** @brief Persistent sdbusplus DBus connection. */
166*f053e6feSPatrick Williams     sdbusplus::bus_t& bus;
1672ec3a7e9SAndrew Geissler 
1680029a5d2SAndrew Geissler     /** @brief Used to subscribe to dbus systemd signals **/
1698f8ba39fSPatrick Williams     sdbusplus::bus::match_t systemdSignals;
170cb781fe1SNagaraju Goruganti 
1712cf2a268SAndrew Geissler     /** @brief Watch for any changes to UPS properties **/
1722cf2a268SAndrew Geissler     std::unique_ptr<sdbusplus::bus::match_t> uPowerPropChangeSignal;
1732cf2a268SAndrew Geissler 
174396ed8a5SAdriana Kobylak     /** @brief Watch for any changes to PowerSystemInputs properties **/
175396ed8a5SAdriana Kobylak     std::unique_ptr<sdbusplus::bus::match_t> powerSysInputsPropChangeSignal;
176396ed8a5SAdriana Kobylak 
17770f36d8eSPotin Lai     /** @brief Chassis id. **/
17870f36d8eSPotin Lai     const size_t id = 0;
17970f36d8eSPotin Lai 
18070f36d8eSPotin Lai     /** @brief Transition state to systemd target mapping table. **/
18170f36d8eSPotin Lai     std::map<Transition, std::string> systemdTargetTable;
18270f36d8eSPotin Lai 
183cb781fe1SNagaraju Goruganti     /** @brief Used to Set value of POHCounter */
18445a1ed71SPatrick Williams     uint32_t pohCounter(uint32_t value) override;
185cb781fe1SNagaraju Goruganti 
186d998f82bSWilliam A. Kennington III     /** @brief Used by the timer to update the POHCounter */
18745a1ed71SPatrick Williams     void pohCallback();
188d998f82bSWilliam A. Kennington III 
189cb781fe1SNagaraju Goruganti     /** @brief Used to restore POHCounter value from persisted file */
190cb781fe1SNagaraju Goruganti     void restorePOHCounter();
191cb781fe1SNagaraju Goruganti 
192cb781fe1SNagaraju Goruganti     /** @brief Serialize and persist requested POH counter.
193cb781fe1SNagaraju Goruganti      *
194cb781fe1SNagaraju Goruganti      *  @return fs::path - pathname of persisted requested POH counter.
195cb781fe1SNagaraju Goruganti      */
196ba182f0cSAllen.Wang     fs::path serializePOH();
197cb781fe1SNagaraju Goruganti 
19881957841SMatt Spinler     /** @brief Deserialize a persisted requested POH counter.
199cb781fe1SNagaraju Goruganti      *
200cb781fe1SNagaraju Goruganti      *  @param[in] retCounter - deserialized POH counter value
201cb781fe1SNagaraju Goruganti      *
202cb781fe1SNagaraju Goruganti      *  @return bool - true if the deserialization was successful, false
203cb781fe1SNagaraju Goruganti      *                 otherwise.
204cb781fe1SNagaraju Goruganti      */
205ba182f0cSAllen.Wang     bool deserializePOH(uint32_t& retCounter);
206cb781fe1SNagaraju Goruganti 
2079eab9861SMatt Spinler     /** @brief Sets the LastStateChangeTime property and persists it. */
2089eab9861SMatt Spinler     void setStateChangeTime();
2099eab9861SMatt Spinler 
2109eab9861SMatt Spinler     /** @brief Serialize the last power state change time.
2119eab9861SMatt Spinler      *
2129eab9861SMatt Spinler      *  Save the time the state changed and the state itself.
2139eab9861SMatt Spinler      *  The state needs to be saved as well so that during rediscovery
2149eab9861SMatt Spinler      *  on reboots there's a way to know not to update the time again.
2159eab9861SMatt Spinler      */
2169eab9861SMatt Spinler     void serializeStateChangeTime();
2179eab9861SMatt Spinler 
2189eab9861SMatt Spinler     /** @brief Deserialize the last power state change time.
2199eab9861SMatt Spinler      *
2209eab9861SMatt Spinler      *  @param[out] time - Deserialized time
2219eab9861SMatt Spinler      *  @param[out] state - Deserialized power state
2229eab9861SMatt Spinler      *
2239eab9861SMatt Spinler      *  @return bool - true if successful, false otherwise.
2249eab9861SMatt Spinler      */
2259eab9861SMatt Spinler     bool deserializeStateChangeTime(uint64_t& time, PowerState& state);
2269eab9861SMatt Spinler 
2279eab9861SMatt Spinler     /** @brief Restores the power state change time.
2289eab9861SMatt Spinler      *
2299eab9861SMatt Spinler      *  The time is loaded into the LastStateChangeTime D-Bus property.
2309eab9861SMatt Spinler      *  On the very first start after this code has been applied but
2319eab9861SMatt Spinler      *  before the state has changed, the LastStateChangeTime value
2329eab9861SMatt Spinler      *  will be zero.
2339eab9861SMatt Spinler      */
2349eab9861SMatt Spinler     void restoreChassisStateChangeTime();
2359eab9861SMatt Spinler 
236d998f82bSWilliam A. Kennington III     /** @brief Timer used for tracking power on hours */
23745a1ed71SPatrick Williams     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pohTimer;
2382c36e5adSBen Tyner 
2392c36e5adSBen Tyner     /** @brief Function to check for a standby voltage regulator fault
2402c36e5adSBen Tyner      *
2412c36e5adSBen Tyner      *  Determine if a standby voltage regulator fault was detected and
2422c36e5adSBen Tyner      *  return true or false accordingly.
2432c36e5adSBen Tyner      *
2442c36e5adSBen Tyner      *  @return true if fault detected, else false
2452c36e5adSBen Tyner      */
2462c36e5adSBen Tyner     bool standbyVoltageRegulatorFault();
2472cf2a268SAndrew Geissler 
2482cf2a268SAndrew Geissler     /** @brief Process UPS property changes
2492cf2a268SAndrew Geissler      *
2502cf2a268SAndrew Geissler      * Instance specific interface to monitor for changes to the UPS
2512cf2a268SAndrew Geissler      * properties which may impact CurrentPowerStatus
2522cf2a268SAndrew Geissler      *
2532cf2a268SAndrew Geissler      * @param[in]  msg              - Data associated with subscribed signal
2542cf2a268SAndrew Geissler      *
2552cf2a268SAndrew Geissler      */
256*f053e6feSPatrick Williams     void uPowerChangeEvent(sdbusplus::message_t& msg);
257396ed8a5SAdriana Kobylak 
258396ed8a5SAdriana Kobylak     /** @brief Process PowerSystemInputs property changes
259396ed8a5SAdriana Kobylak      *
260396ed8a5SAdriana Kobylak      * Instance specific interface to monitor for changes to the
261396ed8a5SAdriana Kobylak      * PowerSystemInputs properties which may impact CurrentPowerStatus
262396ed8a5SAdriana Kobylak      *
263396ed8a5SAdriana Kobylak      * @param[in]  msg              - Data associated with subscribed signal
264396ed8a5SAdriana Kobylak      *
265396ed8a5SAdriana Kobylak      */
266*f053e6feSPatrick Williams     void powerSysInputsChangeEvent(sdbusplus::message_t& msg);
267a90a31a9SAndrew Geissler };
268a90a31a9SAndrew Geissler 
269a90a31a9SAndrew Geissler } // namespace manager
270a90a31a9SAndrew Geissler } // namespace state
271a90a31a9SAndrew Geissler } // namespace phosphor
272