[pfr-manager]Implement BMCBusy Period

BMC busy period is the time for which BMC is busy
(e.g. Flashing).PFR-Manager should not send the security
packets to BMC during that interval.
This patch introduces capability to intimate PFR about
BMC busy period. Also ReadMBRegister D-Bus method is
exposed in order to facilitate OEM IPMI commands to
read the mail box register values


Tested:
Both the dbus methods InitiateBMCBusyPeriod and ReadMBRegister
are working properly now. Logs below:

root@bmc-maca4bf018cc4b0:~# busctl call xyz.openbmc_project.PFR.Manager /xyz/openbmc_project/pfr xyz.openbmc_project.PFR.Mailbox  ReadMBRegister u 0x63
y 0
root@bmc-maca4bf018cc4b0:~# busctl call xyz.openbmc_project.PFR.Manager /xyz/openbmc_project/pfr xyz.openbmc_project.PFR.Mailbox  InitiateBMCBusyPeriod b 1
b true
root@bmc-maca4bf018cc4b0:~# busctl call xyz.openbmc_project.PFR.Manager /xyz/openbmc_project/pfr xyz.openbmc_project.PFR.Mailbox  ReadMBRegister u 0x63
y 1
root@bmc-maca4bf018cc4b0:~# busctl call xyz.openbmc_project.PFR.Manager /xyz/openbmc_project/pfr xyz.openbmc_project.PFR.Mailbox  InitiateBMCBusyPeriod b 0
b true
root@bmc-maca4bf018cc4b0:~# busctl call xyz.openbmc_project.PFR.Manager /xyz/openbmc_project/pfr xyz.openbmc_project.PFR.Mailbox  ReadMBRegister u 0x63
y 0
root@bmc-maca4bf018cc4b0:~#

Signed-off-by: deepak kumar agrawal <deepakx.agrawal@intel.com>
Change-Id: I47acf2a3cb220e55552685cc0eb1fccb2af8adfc
diff --git a/libpfr/inc/pfr.hpp b/libpfr/inc/pfr.hpp
index fb42b23..4110f45 100644
--- a/libpfr/inc/pfr.hpp
+++ b/libpfr/inc/pfr.hpp
@@ -57,5 +57,7 @@
 int setBMCBootCheckpoint(const uint8_t checkPoint);
 void init(std::shared_ptr<sdbusplus::asio::connection> conn,
           bool& i2cConfigLoaded);
+int setBMCBusy(bool setValue);
+int getMBRegister(uint32_t regAddr, uint8_t& mailBoxReply);
 
 } // namespace pfr
diff --git a/libpfr/src/pfr.cpp b/libpfr/src/pfr.cpp
index 0402641..de06125 100644
--- a/libpfr/src/pfr.cpp
+++ b/libpfr/src/pfr.cpp
@@ -599,4 +599,72 @@
     }
 }
 
+static bool setMBRegister(uint32_t regOffset, uint8_t regValue)
+{
+    try
+    {
+        I2CFile mailDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
+        mailDev.i2cWriteByteData(regOffset, regValue);
+        return true;
+    }
+    catch (const std::exception& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Exception caught in setting PFR Mailbox.",
+            phosphor::logging::entry("MSG=%s", e.what()));
+        return false;
+    }
+}
+
+int setBMCBusy(bool setValue)
+{
+    uint32_t bmcBusyReg = 0x63;
+    uint8_t valHigh = 0x01;
+    uint8_t mailBoxReply = 0;
+
+    if (getMBRegister(bmcBusyReg, mailBoxReply))
+    {
+        return -1;
+    }
+    uint8_t readValue = mailBoxReply | valHigh;
+    if (setValue == false)
+    {
+        readValue &= 0b11111110;
+    }
+    if (!setMBRegister(bmcBusyReg, readValue))
+    {
+        return -1;
+    }
+    if (setValue == false)
+    {
+        phosphor::logging::log<phosphor::logging::level::DEBUG>(
+            "Successfully reset the PFR MailBox register.");
+    }
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::DEBUG>(
+            "Successfully set the PFR MailBox to BMCBusy.");
+    }
+    return 0;
+}
+
+int getMBRegister(uint32_t regAddr, uint8_t& mailBoxReply)
+{
+    // Read from PFR CPLD's mailbox register
+    try
+    {
+        I2CFile mailReadDev(i2cBusNumber, i2cSlaveAddress, O_RDWR | O_CLOEXEC);
+
+        mailBoxReply = mailReadDev.i2cReadByteData(regAddr);
+    }
+    catch (const std::exception& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Exception caught in mailbox reading.",
+            phosphor::logging::entry("MSG=%s", e.what()));
+        throw;
+    }
+    return 0;
+}
+
 } // namespace pfr
diff --git a/service/inc/pfr_mgr.hpp b/service/inc/pfr_mgr.hpp
index 8dff6e1..eba9e5b 100644
--- a/service/inc/pfr_mgr.hpp
+++ b/service/inc/pfr_mgr.hpp
@@ -84,6 +84,8 @@
   private:
     sdbusplus::asio::object_server& server;
     std::shared_ptr<sdbusplus::asio::dbus_interface> pfrCfgIface;
+    std::shared_ptr<sdbusplus::asio::dbus_interface> pfrMBIface;
+
     bool internalSet = false;
 
     bool ufmProvisioned;
diff --git a/service/src/pfr_mgr.cpp b/service/src/pfr_mgr.cpp
index fc69fea..c729bba 100644
--- a/service/src/pfr_mgr.cpp
+++ b/service/src/pfr_mgr.cpp
@@ -16,6 +16,8 @@
 
 #include "pfr_mgr.hpp"
 
+#include "file.hpp"
+
 namespace pfr
 {
 
@@ -29,6 +31,10 @@
 std::shared_ptr<sdbusplus::asio::dbus_interface> associationIface;
 std::set<std::tuple<std::string, std::string, std::string>> associations;
 
+using GetSubTreeType = std::vector<
+    std::pair<std::string,
+              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
+
 PfrVersion::PfrVersion(sdbusplus::asio::object_server& srv_,
                        std::shared_ptr<sdbusplus::asio::connection>& conn_,
                        const std::string& path_, const ImageType& imgType_,
@@ -189,6 +195,32 @@
 
     pfrCfgIface->initialize();
 
+    /*BMCBusy period MailBox handling */
+    pfrMBIface = server.add_interface("/xyz/openbmc_project/pfr",
+                                      "xyz.openbmc_project.PFR.Mailbox");
+
+    pfrMBIface->register_method("InitiateBMCBusyPeriod", [](bool setReset) {
+        if (setBMCBusy(setReset) < 0)
+        {
+            return false;
+        }
+        return true;
+    });
+
+    pfrMBIface->register_method("ReadMBRegister", [](uint32_t regAddr) {
+        uint8_t mailBoxReply = 0;
+        try
+        {
+            getMBRegister(regAddr, mailBoxReply);
+        }
+        catch (const std::exception& e)
+        {
+            throw;
+        }
+        return mailBoxReply;
+    });
+    pfrMBIface->initialize();
+
     associationIface =
         server.add_interface("/xyz/openbmc_project/software",
                              "xyz.openbmc_project.Association.Definitions");