pfr-manager: Get i2cBusNumber and i2cSlaveAddress from EntityManager.

Add support to pull i2cBusNumber and i2cSlaveAddress from EntityManager
service dynamically.

Tested:

i2cBusNumber and i2cSlaveAddress are read and updated.

Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
Change-Id: I90fc6f39cfffe609cfefe45fb1e17b9fd6d29f8a
diff --git a/libpfr/inc/pfr.hpp b/libpfr/inc/pfr.hpp
index e327b69..d088f4e 100644
--- a/libpfr/inc/pfr.hpp
+++ b/libpfr/inc/pfr.hpp
@@ -15,6 +15,10 @@
 */
 #pragma once
 
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/asio.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
 #include <string>
 
 namespace pfr
@@ -49,5 +53,7 @@
 int readCpldReg(const ActionType& action, uint8_t& value);
 std::string readCPLDVersion();
 int setBMCBootCheckpoint(const uint8_t checkPoint);
+void init(std::shared_ptr<sdbusplus::asio::connection> conn,
+          bool& i2cConfigLoaded);
 
 } // namespace pfr
diff --git a/libpfr/src/pfr.cpp b/libpfr/src/pfr.cpp
index 856a39c..b52ba22 100644
--- a/libpfr/src/pfr.cpp
+++ b/libpfr/src/pfr.cpp
@@ -27,11 +27,13 @@
 
 namespace pfr
 {
-// TODO: Dynamically pull these values from configuration
-// entity-manager, when needed
-static constexpr int i2cBusNumber = 4;
-// below given is 7bit address. Its 8bit addr is 0x70
-static constexpr int i2cSlaveAddress = 0x38;
+
+using GetSubTreeType = std::vector<
+    std::pair<std::string,
+              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
+
+static int i2cBusNumber = 4;
+static int i2cSlaveAddress = 56;
 
 // CPLD mailbox registers
 static constexpr uint8_t pfrROTId = 0x00;
@@ -87,6 +89,79 @@
 
 bool exceptionFlag = true;
 
+void init(std::shared_ptr<sdbusplus::asio::connection> conn,
+          bool& i2cConfigLoaded)
+{
+    conn->async_method_call(
+        [conn, &i2cConfigLoaded](const boost::system::error_code ec,
+                                 const GetSubTreeType& resp) {
+            if (ec || resp.size() != 1)
+            {
+                return;
+            }
+
+            const std::string& objPath = resp[0].first;
+            const std::string& serviceName = resp[0].second.begin()->first;
+            const std::string match = "Baseboard/PFR";
+            if (boost::ends_with(objPath, match))
+            {
+                // PFR object found.. check for PFR support
+                conn->async_method_call(
+                    [objPath, serviceName, conn, &i2cConfigLoaded](
+                        boost::system::error_code ec,
+                        const std::vector<std::pair<
+                            std::string, std::variant<std::string, uint64_t>>>&
+                            propertiesList) {
+                        if (ec)
+                        {
+                            phosphor::logging::log<
+                                phosphor::logging::level::ERR>(
+                                "Error to Get PFR properties.",
+                                phosphor::logging::entry("MSG=%s",
+                                                         ec.message().c_str()));
+                            return;
+                        }
+
+                        const uint64_t* i2cBus = nullptr;
+                        const uint64_t* address = nullptr;
+
+                        for (const auto& [propName, propVariant] :
+                             propertiesList)
+                        {
+                            if (propName == "Address")
+                            {
+                                address = std::get_if<uint64_t>(&propVariant);
+                            }
+                            else if (propName == "Bus")
+                            {
+                                i2cBus = std::get_if<uint64_t>(&propVariant);
+                            }
+                        }
+
+                        if ((address == nullptr) || (i2cBus == nullptr))
+                        {
+                            phosphor::logging::log<
+                                phosphor::logging::level::ERR>(
+                                "Unable to read the pfr properties");
+                            return;
+                        }
+
+                        i2cBusNumber = static_cast<int>(*i2cBus);
+                        i2cSlaveAddress = static_cast<int>(*address);
+                        i2cConfigLoaded = true;
+                    },
+                    serviceName, objPath, "org.freedesktop.DBus.Properties",
+                    "GetAll", "xyz.openbmc_project.Configuration.PFR");
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+        "/xyz/openbmc_project/inventory/system", 0,
+        std::array<const char*, 1>{"xyz.openbmc_project.Configuration.PFR"});
+    return;
+}
+
 std::string toHexString(const uint8_t val)
 {
     std::stringstream stream;
diff --git a/service/src/mainapp.cpp b/service/src/mainapp.cpp
index dfbf582..5cbe32c 100644
--- a/service/src/mainapp.cpp
+++ b/service/src/mainapp.cpp
@@ -32,6 +32,8 @@
 static uint8_t lastMajorErr = 0;
 static uint8_t lastMinorErr = 0;
 
+static bool i2cConfigLoaded = false;
+
 static bool stateTimerRunning = false;
 bool finishedSettingChkPoint = false;
 static constexpr uint8_t bmcBootFinishedChkPoint = 0x09;
@@ -489,6 +491,7 @@
     pfr::stateTimer = std::make_unique<boost::asio::steady_timer>(io);
     pfr::initTimer = std::make_unique<boost::asio::steady_timer>(io);
     auto server = sdbusplus::asio::object_server(conn, true);
+    pfr::init(conn, pfr::i2cConfigLoaded);
     pfr::monitorSignals(server, conn);
 
     // Update CPLD Version to cpld_active object in settings.