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>
15e426b589SAndrew Geissler #include <experimental/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 
258f8ba39fSPatrick Williams using ChassisInherit = sdbusplus::server::object::object<
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;
29cb781fe1SNagaraju Goruganti namespace fs = std::experimental::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
47*70f36d8eSPotin Lai      * @param[in] id        - Chassis id
48a90a31a9SAndrew Geissler      */
49*70f36d8eSPotin Lai     Chassis(sdbusplus::bus::bus& bus, const char* objPath, size_t id) :
50769a62f1SAndrew Geissler         ChassisInherit(bus, objPath, true), bus(bus),
5158a18013SAndrew Geissler         systemdSignals(
5258a18013SAndrew Geissler             bus,
5358a18013SAndrew Geissler             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
548f8ba39fSPatrick Williams                 sdbusRule::path("/org/freedesktop/systemd1") +
5558a18013SAndrew Geissler                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
5658a18013SAndrew Geissler             std::bind(std::mem_fn(&Chassis::sysStateChange), this,
57d998f82bSWilliam A. Kennington III                       std::placeholders::_1)),
58*70f36d8eSPotin Lai         id(id), pohTimer(sdeventplus::Event::get_default(),
59*70f36d8eSPotin Lai                          std::bind(&Chassis::pohCallback, this),
60*70f36d8eSPotin Lai                          std::chrono::hours{1}, std::chrono::minutes{1})
61dff50ed6SAndrew Geissler     {
620029a5d2SAndrew Geissler         subscribeToSystemdSignals();
630029a5d2SAndrew Geissler 
64*70f36d8eSPotin Lai         createSystemdTargetTable();
65*70f36d8eSPotin Lai 
669eab9861SMatt Spinler         restoreChassisStateChangeTime();
679eab9861SMatt Spinler 
68dff50ed6SAndrew Geissler         determineInitialState();
69dff50ed6SAndrew Geissler 
70cb781fe1SNagaraju Goruganti         restorePOHCounter(); // restore POHCounter from persisted file
71cb781fe1SNagaraju Goruganti 
72dff50ed6SAndrew Geissler         // We deferred this until we could get our property correct
73dff50ed6SAndrew Geissler         this->emit_object_added();
74dff50ed6SAndrew Geissler     }
75dff50ed6SAndrew Geissler 
76a90a31a9SAndrew Geissler     /** @brief Set value of RequestedPowerTransition */
77a90a31a9SAndrew Geissler     Transition requestedPowerTransition(Transition value) override;
78a90a31a9SAndrew Geissler 
79a90a31a9SAndrew Geissler     /** @brief Set value of CurrentPowerState */
80a90a31a9SAndrew Geissler     PowerState currentPowerState(PowerState value) override;
81a90a31a9SAndrew Geissler 
82cb781fe1SNagaraju Goruganti     /** @brief Get value of POHCounter */
8345a1ed71SPatrick Williams     using ChassisInherit::pohCounter;
84cb781fe1SNagaraju Goruganti 
85cb781fe1SNagaraju Goruganti     /** @brief Increment POHCounter if Chassis Power state is ON */
86cb781fe1SNagaraju Goruganti     void startPOHCounter();
87cb781fe1SNagaraju Goruganti 
88a90a31a9SAndrew Geissler   private:
89*70f36d8eSPotin Lai     /** @brief Create systemd target instance names and mapping table */
90*70f36d8eSPotin Lai     void createSystemdTargetTable();
91*70f36d8eSPotin Lai 
920029a5d2SAndrew Geissler     /** @brief Determine initial chassis state and set internally */
930029a5d2SAndrew Geissler     void determineInitialState();
940029a5d2SAndrew Geissler 
958b1f8620SAndrew Geissler     /** @brief Determine status of power into system */
968b1f8620SAndrew Geissler     void determineStatusOfPower();
978b1f8620SAndrew Geissler 
980029a5d2SAndrew Geissler     /**
990029a5d2SAndrew Geissler      * @brief subscribe to the systemd signals
1000029a5d2SAndrew Geissler      *
1010029a5d2SAndrew Geissler      * This object needs to capture when it's systemd targets complete
1020029a5d2SAndrew Geissler      * so it can keep it's state updated
1030029a5d2SAndrew Geissler      *
1040029a5d2SAndrew Geissler      **/
1050029a5d2SAndrew Geissler     void subscribeToSystemdSignals();
1060029a5d2SAndrew Geissler 
107be6efabcSMatthew Barth     /** @brief Start the systemd unit requested
108ce80f24cSAndrew Geissler      *
109be6efabcSMatthew Barth      * This function calls `StartUnit` on the systemd unit given.
110ce80f24cSAndrew Geissler      *
111be6efabcSMatthew Barth      * @param[in] sysdUnit    - Systemd unit
112ce80f24cSAndrew Geissler      */
113be6efabcSMatthew Barth     void startUnit(const std::string& sysdUnit);
114ce80f24cSAndrew Geissler 
115697474c5SJosh D. King     /**
116697474c5SJosh D. King      * @brief Determine if target is active
117697474c5SJosh D. King      *
118697474c5SJosh D. King      * This function determines if the target is active and
119697474c5SJosh D. King      * helps prevent misleading log recorded states.
120697474c5SJosh D. King      *
121697474c5SJosh D. King      * @param[in] target - Target string to check on
122697474c5SJosh D. King      *
123697474c5SJosh D. King      * @return boolean corresponding to state active
124697474c5SJosh D. King      **/
125697474c5SJosh D. King     bool stateActive(const std::string& target);
126697474c5SJosh D. King 
1270029a5d2SAndrew Geissler     /** @brief Check if systemd state change is relevant to this object
1282ec3a7e9SAndrew Geissler      *
1290029a5d2SAndrew Geissler      * Instance specific interface to handle the detected systemd state
1300029a5d2SAndrew Geissler      * change
1312ec3a7e9SAndrew Geissler      *
1322ec3a7e9SAndrew Geissler      * @param[in]  msg       - Data associated with subscribed signal
1332ec3a7e9SAndrew Geissler      *
1342ec3a7e9SAndrew Geissler      */
1358f8ba39fSPatrick Williams     int sysStateChange(sdbusplus::message::message& msg);
1362ec3a7e9SAndrew Geissler 
137a90a31a9SAndrew Geissler     /** @brief Persistent sdbusplus DBus connection. */
138a90a31a9SAndrew Geissler     sdbusplus::bus::bus& bus;
1392ec3a7e9SAndrew Geissler 
1400029a5d2SAndrew Geissler     /** @brief Used to subscribe to dbus systemd signals **/
1418f8ba39fSPatrick Williams     sdbusplus::bus::match_t systemdSignals;
142cb781fe1SNagaraju Goruganti 
1432cf2a268SAndrew Geissler     /** @brief Watch for any changes to UPS properties  **/
1442cf2a268SAndrew Geissler     std::unique_ptr<sdbusplus::bus::match_t> uPowerPropChangeSignal;
1452cf2a268SAndrew Geissler 
146*70f36d8eSPotin Lai     /** @brief Chassis id. **/
147*70f36d8eSPotin Lai     const size_t id = 0;
148*70f36d8eSPotin Lai 
149*70f36d8eSPotin Lai     /** @brief Transition state to systemd target mapping table. **/
150*70f36d8eSPotin Lai     std::map<Transition, std::string> systemdTargetTable;
151*70f36d8eSPotin Lai 
152cb781fe1SNagaraju Goruganti     /** @brief Used to Set value of POHCounter */
15345a1ed71SPatrick Williams     uint32_t pohCounter(uint32_t value) override;
154cb781fe1SNagaraju Goruganti 
155d998f82bSWilliam A. Kennington III     /** @brief Used by the timer to update the POHCounter */
15645a1ed71SPatrick Williams     void pohCallback();
157d998f82bSWilliam A. Kennington III 
158cb781fe1SNagaraju Goruganti     /** @brief Used to restore POHCounter value from persisted file */
159cb781fe1SNagaraju Goruganti     void restorePOHCounter();
160cb781fe1SNagaraju Goruganti 
161cb781fe1SNagaraju Goruganti     /** @brief Serialize and persist requested POH counter.
162cb781fe1SNagaraju Goruganti      *
163cb781fe1SNagaraju Goruganti      *  @param[in] dir - pathname of file where the serialized POH counter will
164cb781fe1SNagaraju Goruganti      *                   be placed.
165cb781fe1SNagaraju Goruganti      *
166cb781fe1SNagaraju Goruganti      *  @return fs::path - pathname of persisted requested POH counter.
167cb781fe1SNagaraju Goruganti      */
168cb781fe1SNagaraju Goruganti     fs::path
16981957841SMatt Spinler         serializePOH(const fs::path& dir = fs::path(POH_COUNTER_PERSIST_PATH));
170cb781fe1SNagaraju Goruganti 
17181957841SMatt Spinler     /** @brief Deserialize a persisted requested POH counter.
172cb781fe1SNagaraju Goruganti      *
173cb781fe1SNagaraju Goruganti      *  @param[in] path - pathname of persisted POH counter file
174cb781fe1SNagaraju Goruganti      *  @param[in] retCounter - deserialized POH counter value
175cb781fe1SNagaraju Goruganti      *
176cb781fe1SNagaraju Goruganti      *  @return bool - true if the deserialization was successful, false
177cb781fe1SNagaraju Goruganti      *                 otherwise.
178cb781fe1SNagaraju Goruganti      */
17981957841SMatt Spinler     bool deserializePOH(const fs::path& path, uint32_t& retCounter);
180cb781fe1SNagaraju Goruganti 
1819eab9861SMatt Spinler     /** @brief Sets the LastStateChangeTime property and persists it. */
1829eab9861SMatt Spinler     void setStateChangeTime();
1839eab9861SMatt Spinler 
1849eab9861SMatt Spinler     /** @brief Serialize the last power state change time.
1859eab9861SMatt Spinler      *
1869eab9861SMatt Spinler      *  Save the time the state changed and the state itself.
1879eab9861SMatt Spinler      *  The state needs to be saved as well so that during rediscovery
1889eab9861SMatt Spinler      *  on reboots there's a way to know not to update the time again.
1899eab9861SMatt Spinler      */
1909eab9861SMatt Spinler     void serializeStateChangeTime();
1919eab9861SMatt Spinler 
1929eab9861SMatt Spinler     /** @brief Deserialize the last power state change time.
1939eab9861SMatt Spinler      *
1949eab9861SMatt Spinler      *  @param[out] time - Deserialized time
1959eab9861SMatt Spinler      *  @param[out] state - Deserialized power state
1969eab9861SMatt Spinler      *
1979eab9861SMatt Spinler      *  @return bool - true if successful, false otherwise.
1989eab9861SMatt Spinler      */
1999eab9861SMatt Spinler     bool deserializeStateChangeTime(uint64_t& time, PowerState& state);
2009eab9861SMatt Spinler 
2019eab9861SMatt Spinler     /** @brief Restores the power state change time.
2029eab9861SMatt Spinler      *
2039eab9861SMatt Spinler      *  The time is loaded into the LastStateChangeTime D-Bus property.
2049eab9861SMatt Spinler      *  On the very first start after this code has been applied but
2059eab9861SMatt Spinler      *  before the state has changed, the LastStateChangeTime value
2069eab9861SMatt Spinler      *  will be zero.
2079eab9861SMatt Spinler      */
2089eab9861SMatt Spinler     void restoreChassisStateChangeTime();
2099eab9861SMatt Spinler 
210d998f82bSWilliam A. Kennington III     /** @brief Timer used for tracking power on hours */
21145a1ed71SPatrick Williams     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> pohTimer;
2122c36e5adSBen Tyner 
2132c36e5adSBen Tyner     /** @brief Function to check for a standby voltage regulator fault
2142c36e5adSBen Tyner      *
2152c36e5adSBen Tyner      *  Determine if a standby voltage regulator fault was detected and
2162c36e5adSBen Tyner      *  return true or false accordingly.
2172c36e5adSBen Tyner      *
2182c36e5adSBen Tyner      *  @return true if fault detected, else false
2192c36e5adSBen Tyner      */
2202c36e5adSBen Tyner     bool standbyVoltageRegulatorFault();
2212cf2a268SAndrew Geissler 
2222cf2a268SAndrew Geissler     /** @brief Process UPS property changes
2232cf2a268SAndrew Geissler      *
2242cf2a268SAndrew Geissler      * Instance specific interface to monitor for changes to the UPS
2252cf2a268SAndrew Geissler      * properties which may impact CurrentPowerStatus
2262cf2a268SAndrew Geissler      *
2272cf2a268SAndrew Geissler      * @param[in]  msg              - Data associated with subscribed signal
2282cf2a268SAndrew Geissler      *
2292cf2a268SAndrew Geissler      */
2302cf2a268SAndrew Geissler     void uPowerChangeEvent(sdbusplus::message::message& msg);
231a90a31a9SAndrew Geissler };
232a90a31a9SAndrew Geissler 
233a90a31a9SAndrew Geissler } // namespace manager
234a90a31a9SAndrew Geissler } // namespace state
235a90a31a9SAndrew Geissler } // namespace phosphor
236