pfr-manager: Read and update last event counts in dbus

Add support to update the last event counts persistently in settings
service.

Tested:
1. BMC update:
Event Logs:
2021-05-09T11:52:21.623486+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC update intent

a. After DC cycle
No duplicate logs occured

b. After BMC reset
Event Logs;
2021-05-09T12:46:17.504866+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC reset detected no duplicate logs occured

c. After AC cycle
No duplicate logs occured

2. BMC update with mismatched SVN
Event Logs:
2021-05-09T17:12:44.301975+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC update intent
2021-05-09T17:12:44.305938+00:00 OpenBMC.0.1.BIOSFirmwareResiliencyError
,Update from BIOS failed(MinorCode:0x02)

a. After DC cycle
No duplicate logs occured

b. After BMC reset
Event Logs:
2021-05-09T17:17:33.389084+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC reset detected no duplicate logs occured

c. After AC cycle
No duplicate logs occured

3. BIOS update with mismatched SVN.
Event Logs:
2021-05-09T14:12:03.123695+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC update intent
2021-05-09T14:12:03.126749+00:00 OpenBMC.0.1.BIOSFirmwareResiliencyError
,Update from BIOS failed(MinorCode:0x02)

a. After DC cycle
No duplicate logs occured

b. After BMC reset
Event Logs:
2021-05-09T15:49:28.742940+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC reset detected and no duplicate logs occured.

c. After AC cycle
No duplicate logs occured

4. CPLD Update.
No Event logs occured and pfr registers are empty.

5. Corrupted BMC update
Event Logs:
1970-01-01T00:00:21.444939+00:00 OpenBMC.0.1.BMCFirmwareRecoveryReason
,BMC active image authentication failure
1970-01-01T00:00:21.448613+00:00 OpenBMC.0.1.BMCFirmwareResiliencyError
,BMC image authentication failed(MinorCode:0x01)

a. After DC cycle
No duplicate logs occured

b. After BMC reset
Event Logs:
1970-01-01T00:00:22.399115+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC reset detected

c. After AC cycle
No duplicate logs occured

6. Corrupted BIOS update
Event Logs:
2021-05-21T12:20:50.170464+00:00 OpenBMC.0.1.BIOSFirmwareRecoveryReason
,BIOS active image authentication failure
2021-05-21T12:20:50.176405+00:00 OpenBMC.0.1.BIOSFirmwareResiliencyError
,BIOS image authentication failed(MinorCode:0x01)

a. After DC cycle
No duplicate logs occured

b. After BMC reset
Event Logs:
2021-05-21T13:39:20.180116+00:00 OpenBMC.0.1.BMCFirmwarePanicReason,
BMC reset detected

c. After AC cycle
No duplicate logs occured

Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
Change-Id: I6decfb4834661ff678098c79af45a116ea1b6cfd
diff --git a/service/src/mainapp.cpp b/service/src/mainapp.cpp
index 5cbe32c..f39c4e0 100644
--- a/service/src/mainapp.cpp
+++ b/service/src/mainapp.cpp
@@ -20,17 +20,11 @@
 #include <systemd/sd-journal.h>
 
 #include <boost/asio.hpp>
+#include <sdbusplus/asio/property.hpp>
+#include <sdbusplus/unpack_properties.hpp>
 
 namespace pfr
 {
-// Caches the last Recovery/Panic Count to
-// identify any new Recovery/panic actions.
-/* TODO: When BMC Reset's, these values will be lost
- * Persist this info using settingsd */
-static uint8_t lastRecoveryCount = 0;
-static uint8_t lastPanicCount = 0;
-static uint8_t lastMajorErr = 0;
-static uint8_t lastMinorErr = 0;
 
 static bool i2cConfigLoaded = false;
 
@@ -188,43 +182,115 @@
         "REDFISH_MESSAGE_ARGS=%s", errorStr.c_str(), NULL);
 }
 
-static void checkAndLogEvents()
+static void
+    handleLastCountChange(std::shared_ptr<sdbusplus::asio::connection> conn,
+                          std::string eventName, uint8_t currentCount)
 {
-    uint8_t currPanicCount = 0;
-    if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
-    {
-        if (lastPanicCount != currPanicCount)
-        {
-            // Update cached data and log redfish event by reading reason.
-            lastPanicCount = currPanicCount;
-            logLastPanicEvent();
-        }
-    }
+    sdbusplus::asio::setProperty(
+        *conn, "xyz.openbmc_project.Settings",
+        "/xyz/openbmc_project/pfr/last_events",
+        "xyz.openbmc_project.PFR.LastEvents", eventName, currentCount,
+        [](boost::system::error_code ec) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "PFR: Unable to update currentCount",
+                    phosphor::logging::entry("MSG=%s", ec.message().c_str()));
+                return;
+            }
+        });
+    return;
+}
 
-    uint8_t currRecoveryCount = 0;
-    if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
-    {
-        if (lastRecoveryCount != currRecoveryCount)
-        {
-            // Update cached data and log redfish event by reading reason.
-            lastRecoveryCount = currRecoveryCount;
-            logLastRecoveryEvent();
-        }
-    }
+static void
+    checkAndLogEvents(std::shared_ptr<sdbusplus::asio::connection>& conn)
+{
+    sdbusplus::asio::getAllProperties(
+        *conn, "xyz.openbmc_project.Settings",
+        "/xyz/openbmc_project/pfr/last_events",
+        "xyz.openbmc_project.PFR.LastEvents",
+        [conn](
+            boost::system::error_code ec,
+            std::vector<
+                std::pair<std::string, std::variant<std::monostate, uint8_t>>>&
+                properties) {
+            if (ec)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "PFR: Unable get PFR last events",
+                    phosphor::logging::entry("MSG=%s", ec.message().c_str()));
+                return;
+            }
+            uint8_t lastRecoveryCount = 0;
+            uint8_t lastPanicCount = 0;
+            uint8_t lastMajorErr = 0;
+            uint8_t lastMinorErr = 0;
 
-    uint8_t majorErr = 0;
-    uint8_t minorErr = 0;
-    if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
-        (0 == readCpldReg(ActionType::minorError, minorErr)))
-    {
-        if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
-        {
-            lastMajorErr = majorErr;
-            lastMinorErr = minorErr;
+            try
+            {
+                sdbusplus::unpackProperties(
+                    properties, "lastRecoveryCount", lastRecoveryCount,
+                    "lastPanicCount", lastPanicCount, "lastMajorErr",
+                    lastMajorErr, "lastMinorErr", lastMinorErr);
+            }
+            catch (const sdbusplus::exception::UnpackPropertyError& error)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "PFR: Unpack error",
+                    phosphor::logging::entry("MSG=%s", error.what()));
+                return;
+            }
 
-            logResiliencyErrorEvent(majorErr, minorErr);
-        }
-    }
+            uint8_t currPanicCount = 0;
+            if (0 == readCpldReg(ActionType::panicCount, currPanicCount))
+            {
+                if (lastPanicCount != currPanicCount)
+                {
+                    // Update cached data to dbus and log redfish
+                    // event by reading reason.
+                    handleLastCountChange(conn, "lastPanicCount",
+                                          currPanicCount);
+                    if (currPanicCount)
+                    {
+                        logLastPanicEvent();
+                    }
+                }
+            }
+
+            uint8_t currRecoveryCount = 0;
+            if (0 == readCpldReg(ActionType::recoveryCount, currRecoveryCount))
+            {
+                if (lastRecoveryCount != currRecoveryCount)
+                {
+                    // Update cached data to dbus and log redfish
+                    // event by reading reason.
+                    handleLastCountChange(conn, "lastRecoveryCount",
+                                          currRecoveryCount);
+                    if (currRecoveryCount)
+                    {
+                        logLastRecoveryEvent();
+                    }
+                }
+            }
+
+            uint8_t majorErr = 0;
+            uint8_t minorErr = 0;
+            if ((0 == readCpldReg(ActionType::majorError, majorErr)) &&
+                (0 == readCpldReg(ActionType::minorError, minorErr)))
+            {
+                if ((lastMajorErr != majorErr) || (lastMinorErr != minorErr))
+                {
+                    // Update cached data to dbus and log redfish event by
+                    // reading reason.
+                    handleLastCountChange(conn, "lastMajorErr", majorErr);
+                    handleLastCountChange(conn, "lastMinorErr", minorErr);
+                    if (majorErr && minorErr)
+                    {
+                        logResiliencyErrorEvent(majorErr, minorErr);
+                    }
+                }
+            }
+        });
 }
 
 static void monitorPlatformStateChange(
@@ -245,7 +311,7 @@
                 // Platform State Monitor - Timer cancelled.
                 return;
             }
-            checkAndLogEvents();
+            checkAndLogEvents(conn);
             monitorPlatformStateChange(server, conn);
         });
 }
@@ -363,7 +429,7 @@
                              (stateTimerRunning))
                     {
                         stateTimer->cancel();
-                        checkAndLogEvents();
+                        checkAndLogEvents(conn);
                         stateTimerRunning = false;
                     }
                 }
@@ -408,7 +474,7 @@
                              (stateTimerRunning))
                     {
                         stateTimer->cancel();
-                        checkAndLogEvents();
+                        checkAndLogEvents(conn);
                         stateTimerRunning = false;
                     }
                 }
@@ -444,7 +510,7 @@
                         (stateTimerRunning))
                     {
                         stateTimer->cancel();
-                        checkAndLogEvents();
+                        checkAndLogEvents(conn);
                         stateTimerRunning = false;
                     }
                     else if (!stateTimerRunning)
@@ -457,7 +523,7 @@
         });
 
     // First time, check and log events if any.
-    checkAndLogEvents();
+    checkAndLogEvents(conn);
 }
 
 static void updateCPLDversion(std::shared_ptr<sdbusplus::asio::connection> conn)