Add API to create fru records only for present frus.

This commit builds the fru records only for the present
frus. Any item which is a FRU should by default implement
the Inventory.Item Interface and host the present property.
So, if the present property is not hosted then FRU is absent.

Signed-off-by: Sridevi Ramesh <sridevra@in.ibm.com>
Change-Id: I5534d6cc1a9f7a1b329975cdd5de54110f456f39
diff --git a/common/utils.cpp b/common/utils.cpp
index 6c82db7..9173471 100644
--- a/common/utils.cpp
+++ b/common/utils.cpp
@@ -22,7 +22,6 @@
 {
 namespace utils
 {
-
 constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
 constexpr auto mapperPath = "/xyz/openbmc_project/object_mapper";
 constexpr auto mapperInterface = "xyz.openbmc_project.ObjectMapper";
@@ -581,5 +580,25 @@
     return ss.str();
 }
 
+bool checkForFruPresence(const std::string& objPath)
+{
+    bool isPresent = false;
+    static constexpr auto presentInterface =
+        "xyz.openbmc_project.Inventory.Item";
+    static constexpr auto presentProperty = "Present";
+    try
+    {
+        auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
+            objPath.c_str(), presentProperty, presentInterface);
+        isPresent = std::get<bool>(propVal);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        std::cerr << "Failed to check for FRU presence for " << objPath
+                  << " ERROR =" << e.what() << std::endl;
+    }
+    return isPresent;
+}
+
 } // namespace utils
 } // namespace pldm
diff --git a/common/utils.hpp b/common/utils.hpp
index a99c47c..025119c 100644
--- a/common/utils.hpp
+++ b/common/utils.hpp
@@ -26,7 +26,6 @@
 {
 namespace utils
 {
-
 namespace fs = std::filesystem;
 using Json = nlohmann::json;
 constexpr bool Tx = true;
@@ -150,6 +149,8 @@
 using Interfaces = std::vector<std::string>;
 using MapperServiceMap = std::vector<std::pair<ServiceName, Interfaces>>;
 using GetSubTreeResponse = std::vector<std::pair<ObjectPath, MapperServiceMap>>;
+using PropertyMap = std::map<std::string, PropertyValue>;
+using InterfaceMap = std::map<std::string, PropertyMap>;
 
 /**
  * @brief The interface for DBusHandler
@@ -408,5 +409,12 @@
  */
 std::string getCurrentSystemTime();
 
+/** @brief checks if the FRU is actually present.
+ *  @param[in] objPath - FRU object path.
+ *
+ *  @return bool to indicate presence or absence of FRU.
+ */
+bool checkForFruPresence(const std::string& objPath);
+
 } // namespace utils
 } // namespace pldm
diff --git a/libpldmresponder/fru.cpp b/libpldmresponder/fru.cpp
index afb5637..ef032b4 100644
--- a/libpldmresponder/fru.cpp
+++ b/libpldmresponder/fru.cpp
@@ -15,10 +15,8 @@
 
 namespace pldm
 {
-
 namespace responder
 {
-
 void FruImpl::buildFRUTable()
 {
     if (isBuilt)
@@ -52,7 +50,13 @@
     for (const auto& object : objects)
     {
         const auto& interfaces = object.second;
-
+        bool isPresent = pldm::utils::checkForFruPresence(object.first.str);
+        // Do not create fru record if fru is not present.
+        // Pick up the next available fru.
+        if (!isPresent)
+        {
+            continue;
+        }
         for (const auto& interface : interfaces)
         {
             if (itemIntfsLookup.find(interface.first) != itemIntfsLookup.end())
@@ -116,7 +120,7 @@
 
     if (table.size())
     {
-        padBytes = utils::getNumPadBytes(table.size());
+        padBytes = pldm::utils::getNumPadBytes(table.size());
         table.resize(table.size() + padBytes, 0);
 
         // Calculate the checksum
@@ -280,7 +284,7 @@
         return PLDM_FRU_DATA_STRUCTURE_TABLE_UNAVAILABLE;
     }
 
-    auto pads = utils::getNumPadBytes(recordTableSize);
+    auto pads = pldm::utils::getNumPadBytes(recordTableSize);
     crc32(fruData.data(), recordTableSize + pads);
 
     auto iter = fruData.begin() + recordTableSize + pads;
@@ -293,7 +297,6 @@
 
 namespace fru
 {
-
 Response Handler::getFRURecordTableMetadata(const pldm_msg* request,
                                             size_t /*payloadLength*/)
 {