BMC state manager support for LastRebootTime

Use the uptime value to calculate the time of the last
BMC reboot when the LastRebootTime property is read.

Calculates it on the fly instead of once at startup so that
if someone changes the BMC time the value will still be
accurate.

Resolves openbmc/openbmc#3159

Tested: Verify the property returns the right value.

Change-Id: I4bc8d2cdf18c225b24c98d9567d053c3246b7506
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/bmc_state_manager.cpp b/bmc_state_manager.cpp
index 667e300..5389fc5 100644
--- a/bmc_state_manager.cpp
+++ b/bmc_state_manager.cpp
@@ -1,6 +1,5 @@
-#include <iostream>
-#include <string>
 #include <phosphor-logging/log.hpp>
+#include <sys/sysinfo.h>
 #include "bmc_state_manager.hpp"
 
 namespace phosphor
@@ -164,6 +163,21 @@
     return server::BMC::currentBMCState(value);
 }
 
+uint64_t BMC::lastRebootTime() const
+{
+    using namespace std::chrono;
+    struct sysinfo info;
+
+    auto rc = sysinfo(&info);
+    assert(rc == 0);
+
+    // Since uptime is in seconds, also get the current time in seconds.
+    auto now = time_point_cast<seconds>(system_clock::now());
+    auto rebootTime = now - seconds(info.uptime);
+
+    return duration_cast<milliseconds>(rebootTime.time_since_epoch()).count();
+}
+
 } // namespace manager
 } // namespace state
 } // namepsace phosphor
diff --git a/bmc_state_manager.hpp b/bmc_state_manager.hpp
index b060ccd..c55c822 100644
--- a/bmc_state_manager.hpp
+++ b/bmc_state_manager.hpp
@@ -50,6 +50,16 @@
     /** @brief Set value of CurrentBMCState **/
     BMCState currentBMCState(BMCState value) override;
 
+    /** @brief Returns the last time the BMC was rebooted
+     *
+     *  @details Uses uptime information to determine when
+     *           the BMC was last rebooted.
+     *
+     *  @return uint64_t - Epoch time, in milliseconds, of the
+     *                     last reboot.
+     */
+    uint64_t lastRebootTime() const override;
+
   private:
     /**
      * @brief discover the state of the bmc