PEL: Add BMC uptime to PELs in UserData section

A UserData section has been added to each PEL with additional debug
information, now there is a need to add the output of the uptime
command to UserData and display it, but for Hostboot doesn't care
about this property, so skip adding it here it.

Tested: unit test passed
"User Data 0": {
    "Section Version": "1",
    "Sub-section type": "1",
    "Created by": "0x2000",
    ...
    "Uptime": "3y 332d 21h 33m 9s",
    "Load": "1.47 0.94 0.61",
},

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I3d4c78bb1650da9a91804fc83de60597992ffc8a
diff --git a/extensions/openpower-pels/data_interface.hpp b/extensions/openpower-pels/data_interface.hpp
index 4095cce..c0e8c45 100644
--- a/extensions/openpower-pels/data_interface.hpp
+++ b/extensions/openpower-pels/data_interface.hpp
@@ -4,6 +4,7 @@
 #include "dbus_watcher.hpp"
 
 #include <filesystem>
+#include <fstream>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/bus/match.hpp>
@@ -144,6 +145,91 @@
     }
 
     /**
+     * @brief Returns the time the system was running.
+     *
+     * @return std::optional<uint64_t> - The System uptime or std::nullopt
+     */
+    std::optional<uint64_t> getUptimeInSeconds() const
+    {
+        std::ifstream versionFile{"/proc/uptime"};
+        std::string line{};
+
+        std::getline(versionFile, line);
+        auto pos = line.find(" ");
+        if (pos == std::string::npos)
+        {
+            return std::nullopt;
+        }
+
+        uint64_t seconds = atol(line.substr(0, pos).c_str());
+        if (seconds == 0)
+        {
+            return std::nullopt;
+        }
+
+        return seconds;
+    }
+
+    /**
+     * @brief Returns the time the system was running.
+     *
+     * @param[in] seconds - The number of seconds the system has been running
+     *
+     * @return std::string - days/hours/minutes/seconds
+     */
+    std::string getBMCUptime(uint64_t seconds) const
+    {
+        time_t t(seconds);
+        tm* p = gmtime(&t);
+
+        std::string uptime = std::to_string(p->tm_year - 70) + "y " +
+                             std::to_string(p->tm_yday) + "d " +
+                             std::to_string(p->tm_hour) + "h " +
+                             std::to_string(p->tm_min) + "m " +
+                             std::to_string(p->tm_sec) + "s";
+
+        return uptime;
+    }
+
+    /**
+     * @brief Returns the system load average over the past 1 minute, 5 minutes
+     *        and 15 minutes.
+     *
+     * @return std::string - The system load average
+     */
+    std::string getBMCLoadAvg() const
+    {
+        std::string loadavg{};
+
+        std::ifstream loadavgFile{"/proc/loadavg"};
+        std::string line;
+        std::getline(loadavgFile, line);
+
+        size_t count = 3;
+        for (size_t i = 0; i < count; i++)
+        {
+            auto pos = line.find(" ");
+            if (pos == std::string::npos)
+            {
+                return {};
+            }
+
+            if (i != count - 1)
+            {
+                loadavg.append(line.substr(0, pos + 1));
+            }
+            else
+            {
+                loadavg.append(line.substr(0, pos));
+            }
+
+            line = line.substr(pos + 1);
+        }
+
+        return loadavg;
+    }
+
+    /**
      * @brief Returns the 'send event logs to host' setting.
      *
      * @return bool - If sending PELs to the host is enabled.