Add ECC metadata

This change adds a ECC service that handles memory error and
to add new IPMI SEL records to the journal with the correct
metadata.

Tested:

CE Error:
1. Triger memory ce error:
devmem 0xf0824178 32 0x7501

2. ipmi sel list should log ce error:
1 |  Pre-Init  |0000015435| Memory #0xf0 | Correctable ECC | Asserted

UE Error:
1. Triger memory ue error:
devmem 0xf0824178 32 0x301

2.ipmi sel list should log ue error:
2 |  Pre-Init  |0000001677| Memory #0xf0 | Uncorrectable ECC | Asserted

Change-Id: Ia63a62c2e80697639fef4c4e114fee52f65c71af
Signed-off-by: Will Liang <will.liang@quantatw.com>
diff --git a/ecc_manager.hpp b/ecc_manager.hpp
new file mode 100644
index 0000000..bbad72c
--- /dev/null
+++ b/ecc_manager.hpp
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <sdeventplus/clock.hpp>
+#include <sdeventplus/event.hpp>
+#include <sdeventplus/utility/timer.hpp>
+#include <xyz/openbmc_project/Memory/MemoryECC/server.hpp>
+
+namespace phosphor
+{
+namespace memory
+{
+
+template <typename... T>
+using ServerObject = typename sdbusplus::server::object::object<T...>;
+
+using EccInterface = sdbusplus::xyz::openbmc_project::Memory::server::MemoryECC;
+using EccObject = ServerObject<EccInterface>;
+/** @class
+ *  @brief Manages ECC
+ */
+class ECC : sdbusplus::server::object::object<
+                sdbusplus::xyz::openbmc_project::Memory::server::MemoryECC>
+{
+  public:
+    ECC() = delete;
+    ~ECC() = default;
+    ECC(const ECC&) = delete;
+    ECC& operator=(const ECC&) = delete;
+    ECC(ECC&&) = default;
+    ECC& operator=(ECC&&) = default;
+
+    /** @brief Constructs
+     *
+     * @param[in] bus     - Handle to system dbus
+     * @param[in] objPath - The Dbus path
+     */
+    ECC(sdbusplus::bus::bus& bus, const std::string& objPath) :
+        sdbusplus::server::object::object<
+            sdbusplus::xyz::openbmc_project::Memory::server::MemoryECC>(
+            bus, objPath.c_str()),
+        _bus(bus), _event(sdeventplus::Event::get_default()),
+        _timer(_event, std::bind(&ECC::read, this)){
+            // Nothing to do here
+        };
+
+    int64_t previousCeCounter = 0;
+    int64_t previousUeCounter = 0;
+    int64_t maxECCLog = 0;
+
+    void run();
+    void controlEDACReport(std::string);
+
+  private:
+    /** @brief sdbusplus bus client connection. */
+    sdbusplus::bus::bus& _bus;
+    /** @brief the Event Loop structure */
+    sdeventplus::Event _event;
+    /** @brief Read Timer */
+    sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer;
+    /** @brief Read sysfs entries */
+    void read();
+
+    /** @brief Set up D-Bus object init */
+    void init();
+
+    std::string getValue(std::string);
+
+    void writeValue(std::string, std::string);
+    // set ce_count to dbus
+    int checkCeCount();
+    // set ue_count to dbus
+    int checkUeCount();
+    // set eccErrorCount to dbus
+    void checkEccLogFull(int64_t, int64_t);
+
+    void resetCounter();
+    // set maxECCLog value
+    void getMaxLogValue();
+
+    void addSELLog(std::string, std::string, std::vector<uint8_t>, bool,
+                   uint16_t);
+};
+
+} // namespace memory
+} // namespace phosphor