Add Chassis POH Counter

Added 32-bit counter, which shows how many hours the system has been
running. The value is a cumulative one and includes all working hours
since production. If the chassis state is Powered-on, This will be
incremented by one for every hour. It won't get updated when the
chassis state is powered-off.

Resolves openbmc/openbmc#2979

Change-Id: I18e9bb571d1a6e401b25450168249f70891be665
Signed-off-by: Nagaraju Goruganti <ngorugan@in.ibm.com>
diff --git a/chassis_state_manager.hpp b/chassis_state_manager.hpp
index 54f0afd..a1fcb04 100644
--- a/chassis_state_manager.hpp
+++ b/chassis_state_manager.hpp
@@ -1,8 +1,13 @@
 #pragma once
 
 #include <functional>
+#include <experimental/filesystem>
+#include <cereal/cereal.hpp>
 #include <sdbusplus/bus.hpp>
 #include "xyz/openbmc_project/State/Chassis/server.hpp"
+#include "xyz/openbmc_project/State/PowerOnHours/server.hpp"
+#include "config.h"
+#include "timer.hpp"
 
 namespace phosphor
 {
@@ -10,10 +15,19 @@
 {
 namespace manager
 {
+namespace POH
+{
+
+using namespace std::chrono_literals;
+constexpr auto hour = 3600s; // seconds Per Hour
+
+} // namespace  POH
 
 using ChassisInherit = sdbusplus::server::object::object<
-    sdbusplus::xyz::openbmc_project::State::server::Chassis>;
+    sdbusplus::xyz::openbmc_project::State::server::Chassis,
+    sdbusplus::xyz::openbmc_project::State::server::PowerOnHours>;
 namespace sdbusRule = sdbusplus::bus::match::rules;
+namespace fs = std::experimental::filesystem;
 
 /** @class Chassis
  *  @brief OpenBMC chassis state management implementation.
@@ -49,6 +63,8 @@
 
         determineInitialState();
 
+        restorePOHCounter(); // restore POHCounter from persisted file
+
         // We deferred this until we could get our property correct
         this->emit_object_added();
     }
@@ -59,6 +75,12 @@
     /** @brief Set value of CurrentPowerState */
     PowerState currentPowerState(PowerState value) override;
 
+    /** @brief Get value of POHCounter */
+    using ChassisInherit::pOHCounter;
+
+    /** @brief Increment POHCounter if Chassis Power state is ON */
+    void startPOHCounter();
+
   private:
     /** @brief Determine initial chassis state and set internally */
     void determineInitialState();
@@ -108,6 +130,63 @@
 
     /** @brief Used to subscribe to dbus systemd signals **/
     sdbusplus::bus::match_t systemdSignals;
+
+    /** @brief Used to Set value of POHCounter */
+    uint32_t pOHCounter(uint32_t value) override;
+
+    /** @brief Used to restore POHCounter value from persisted file */
+    void restorePOHCounter();
+
+    /** @brief Function required by Cereal to perform serialization.
+     *
+     *  @tparam Archive - Cereal archive type (json in our case).
+     *  @param[in] archive - reference to Cereal archive.
+     *  @param[in] version - Class version that enables handling
+     *                       a serialized data across code levels
+     */
+    template <class Archive>
+    inline void save(Archive& archive, const std::uint32_t version) const
+    {
+        archive(pOHCounter());
+    }
+
+    /** @brief Function required by Cereal to perform deserialization.
+     *
+     *  @tparam Archive - Cereal archive type (json in our case).
+     *  @param[in] archive - reference to Cereal archive.
+     *  @param[in] version - Class version that enables handling
+     *                       a serialized data across code levels
+     */
+    template <class Archive>
+    inline void load(Archive& archive, const std::uint32_t version)
+    {
+        uint32_t value;
+        archive(value);
+        pOHCounter(value);
+    }
+
+    /** @brief Serialize and persist requested POH counter.
+     *
+     *  @param[in] dir - pathname of file where the serialized POH counter will
+     *                   be placed.
+     *
+     *  @return fs::path - pathname of persisted requested POH counter.
+     */
+    fs::path
+        serialize(const fs::path& dir = fs::path(POH_COUNTER_PERSIST_PATH));
+
+    /** @brief Deserialze a persisted requested POH counter.
+     *
+     *  @param[in] path - pathname of persisted POH counter file
+     *  @param[in] retCounter - deserialized POH counter value
+     *
+     *  @return bool - true if the deserialization was successful, false
+     *                 otherwise.
+     */
+    bool deserialize(const fs::path& path, uint32_t& retCounter);
+
+    /** @brief Timer */
+    std::unique_ptr<phosphor::state::manager::Timer> timer;
 };
 
 } // namespace manager