Merge entity association PDRs

This commit enables merging entity association PDRs from the host into
the BMC's PDR repo. Entities from the host are inserted into the
appropriate location in the entity tree maintained by the BMC.

Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: Ie9fa46d9f8512fad6c04069e4fc65785972fbf64
diff --git a/host_pdr_handler.cpp b/host_pdr_handler.cpp
index 3cd7873..c627b0b 100644
--- a/host_pdr_handler.cpp
+++ b/host_pdr_handler.cpp
@@ -1,10 +1,62 @@
+#include "config.h"
+
 #include "host_pdr_handler.hpp"
 
+#include <fstream>
+#include <nlohmann/json.hpp>
+
 #include "libpldm/requester/pldm.h"
 
 namespace pldm
 {
 
+using Json = nlohmann::json;
+namespace fs = std::filesystem;
+constexpr auto fruJson = "host_frus.json";
+const Json emptyJson{};
+const std::vector<Json> emptyJsonList{};
+
+HostPDRHandler::HostPDRHandler(int mctp_fd, uint8_t mctp_eid,
+                               sdeventplus::Event& event, pldm_pdr* repo,
+                               pldm_entity_association_tree* entityTree,
+                               Requester& requester) :
+    mctp_fd(mctp_fd),
+    mctp_eid(mctp_eid), event(event), repo(repo), entityTree(entityTree),
+    requester(requester)
+{
+    fs::path hostFruJson(fs::path(HOST_JSONS_DIR) / fruJson);
+    if (fs::exists(hostFruJson))
+    {
+        try
+        {
+            std::ifstream jsonFile(hostFruJson);
+            auto data = Json::parse(jsonFile, nullptr, false);
+            if (data.is_discarded())
+            {
+                std::cerr << "Parsing Host FRU json file failed" << std::endl;
+            }
+            else
+            {
+                auto entities = data.value("entities", emptyJsonList);
+                for (auto& entity : entities)
+                {
+                    EntityType entityType = entity.value("entity_type", 0);
+                    auto parent = entity.value("parent", emptyJson);
+                    pldm_entity p{};
+                    p.entity_type = parent.value("entity_type", 0);
+                    p.entity_instance_num = parent.value("entity_instance", 0);
+                    parents.emplace(entityType, std::move(p));
+                }
+            }
+        }
+        catch (const std::exception& e)
+        {
+            std::cerr << "Parsing Host FRU json file failed, exception = "
+                      << e.what() << std::endl;
+        }
+    }
+}
+
 void HostPDRHandler::fetchPDR(std::vector<uint32_t>&& recordHandles)
 {
     pdrRecordHandles.clear();
@@ -89,10 +141,63 @@
             }
             else
             {
-                pldm_pdr_add(repo, pdr.data(), respCount, 0);
+                auto pdrHdr = reinterpret_cast<pldm_pdr_hdr*>(pdr.data());
+                if (pdrHdr->type == PLDM_PDR_ENTITY_ASSOCIATION)
+                {
+                    mergeEntityAssociations(pdr);
+                }
+                else
+                {
+                    pldm_pdr_add(repo, pdr.data(), respCount, 0, true);
+                }
             }
         }
     }
 }
 
+bool HostPDRHandler::getParent(EntityType type, pldm_entity& parent)
+{
+    auto found = parents.find(type);
+    if (found != parents.end())
+    {
+        parent.entity_type = found->second.entity_type;
+        parent.entity_instance_num = found->second.entity_instance_num;
+        return true;
+    }
+
+    return false;
+}
+
+void HostPDRHandler::mergeEntityAssociations(const std::vector<uint8_t>& pdr)
+{
+    size_t numEntities{};
+    pldm_entity* entities = nullptr;
+    bool merged = false;
+    auto entityPdr = reinterpret_cast<pldm_pdr_entity_association*>(
+        const_cast<uint8_t*>(pdr.data()) + sizeof(pldm_pdr_hdr));
+
+    pldm_entity_association_pdr_extract(pdr.data(), pdr.size(), &numEntities,
+                                        &entities);
+    for (size_t i = 0; i < numEntities; ++i)
+    {
+        pldm_entity parent{};
+        if (getParent(entities[i].entity_type, parent))
+        {
+            auto node = pldm_entity_association_tree_find(entityTree, &parent);
+            if (node)
+            {
+                pldm_entity_association_tree_add(entityTree, &entities[i], node,
+                                                 entityPdr->association_type);
+                merged = true;
+            }
+        }
+    }
+    free(entities);
+
+    if (merged)
+    {
+        pldm_entity_association_pdr_add(entityTree, repo, true);
+    }
+}
+
 } // namespace pldm
diff --git a/host_pdr_handler.hpp b/host_pdr_handler.hpp
index dc5462f..af1fbab 100644
--- a/host_pdr_handler.hpp
+++ b/host_pdr_handler.hpp
@@ -3,6 +3,7 @@
 #include "dbus_impl_requester.hpp"
 #include "utils.hpp"
 
+#include <map>
 #include <memory>
 #include <sdeventplus/event.hpp>
 #include <sdeventplus/source/event.hpp>
@@ -16,6 +17,7 @@
 namespace pldm
 {
 
+using EntityType = uint16_t;
 // vector which would hold the PDR record handle data returned by
 // pldmPDRRepositoryChgEvent event data
 using ChangeEntry = uint32_t;
@@ -45,15 +47,13 @@
      *  @param[in] mctp_eid - MCTP EID of host firmware
      *  @param[in] event - reference of main event loop of pldmd
      *  @param[in] repo - pointer to BMC's primary PDR repo
+     *  @param[in] tree - pointer to BMC's entity association tree
      *  @param[in] requester - reference to Requester object
      */
     explicit HostPDRHandler(int mctp_fd, uint8_t mctp_eid,
                             sdeventplus::Event& event, pldm_pdr* repo,
-                            Requester& requester) :
-        mctp_fd(mctp_fd),
-        mctp_eid(mctp_eid), event(event), repo(repo), requester(requester)
-    {
-    }
+                            pldm_entity_association_tree* entityTree,
+                            Requester& requester);
 
     /** @brief fetch PDRs from host firmware. See @class.
      *  @param[in] recordHandles - list of record handles pointing to host's
@@ -68,6 +68,21 @@
      */
     void _fetchPDR(sdeventplus::source::EventBase& source);
 
+    /** @brief Merge host firmware's entity association PDRs into BMC's
+     *  @details A merge operation involves adding a pldm_entity under the
+     *  appropriate parent, and updating container ids.
+     *  @param[in] pdr - entity association pdr
+     */
+    void mergeEntityAssociations(const std::vector<uint8_t>& pdr);
+
+    /** @brief Find parent of input entity type, from the entity association
+     *  tree
+     *  @param[in] type - PLDM entity type
+     *  @param[out] parent - PLDM entity information of parent
+     *  @return bool - true if parent found, false otherwise
+     */
+    bool getParent(EntityType type, pldm_entity& parent);
+
     /** @brief fd of MCTP communications socket */
     int mctp_fd;
     /** @brief MCTP EID of host firmware */
@@ -78,6 +93,8 @@
     sdeventplus::Event& event;
     /** @brief pointer to BMC's primary PDR repo, host PDRs are added here */
     pldm_pdr* repo;
+    /** @brief Pointer to BMC's entity association tree */
+    pldm_entity_association_tree* entityTree;
     /** @brief reference to Requester object, primarily used to access API to
      *  obtain PLDM instance id.
      */
@@ -86,6 +103,10 @@
     std::unique_ptr<sdeventplus::source::Defer> pdrFetchEvent;
     /** @brief list of PDR record handles pointing to host's PDRs */
     PDRRecordHandles pdrRecordHandles;
+    /** @brief maps an entity type to parent pldm_entity from the BMC's entity
+     *  association tree
+     */
+    std::map<EntityType, pldm_entity> parents;
 };
 
 } // namespace pldm
diff --git a/libpldm/pdr.c b/libpldm/pdr.c
index b29f6f1..64c314b 100644
--- a/libpldm/pdr.c
+++ b/libpldm/pdr.c
@@ -9,6 +9,7 @@
 	uint32_t size;
 	uint8_t *data;
 	struct pldm_pdr_record *next;
+	bool is_remote;
 } pldm_pdr_record;
 
 typedef struct pldm_pdr {
@@ -59,7 +60,7 @@
 
 static pldm_pdr_record *make_new_record(const pldm_pdr *repo,
 					const uint8_t *data, uint32_t size,
-					uint32_t record_handle)
+					uint32_t record_handle, bool is_remote)
 {
 	assert(repo != NULL);
 	assert(size != 0);
@@ -69,6 +70,7 @@
 	record->record_handle =
 	    record_handle == 0 ? get_new_record_handle(repo) : record_handle;
 	record->size = size;
+	record->is_remote = is_remote;
 	if (data != NULL) {
 		record->data = malloc(size);
 		assert(record->data != NULL);
@@ -91,13 +93,13 @@
 }
 
 uint32_t pldm_pdr_add(pldm_pdr *repo, const uint8_t *data, uint32_t size,
-		      uint32_t record_handle)
+		      uint32_t record_handle, bool is_remote)
 {
 	assert(size != 0);
 	assert(data != NULL);
 
 	pldm_pdr_record *record =
-	    make_new_record(repo, data, size, record_handle);
+	    make_new_record(repo, data, size, record_handle, is_remote);
 	add_record(repo, record);
 
 	return record->record_handle;
@@ -237,6 +239,13 @@
 	return record->record_handle;
 }
 
+inline bool pldm_pdr_record_is_remote(const pldm_pdr_record *record)
+{
+	assert(record != NULL);
+
+	return record->is_remote;
+}
+
 uint32_t pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
 				     uint16_t fru_rsi, uint16_t entity_type,
 				     uint16_t entity_instance_num,
@@ -261,7 +270,7 @@
 	fru->entity_instance_num = htole16(entity_instance_num);
 	fru->container_id = htole16(container_id);
 
-	return pldm_pdr_add(repo, data, size, 0);
+	return pldm_pdr_add(repo, data, size, 0, false);
 }
 
 const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
@@ -495,7 +504,8 @@
 static void _entity_association_pdr_add_entry(pldm_entity_node *curr,
 					      pldm_pdr *repo, uint16_t size,
 					      uint8_t contained_count,
-					      uint8_t association_type)
+					      uint8_t association_type,
+					      bool is_remote)
 {
 	uint8_t pdr[size];
 	uint8_t *start = pdr;
@@ -537,11 +547,11 @@
 		node = node->next_sibling;
 	}
 
-	pldm_pdr_add(repo, pdr, size, 0);
+	pldm_pdr_add(repo, pdr, size, 0, is_remote);
 }
 
 static void entity_association_pdr_add_entry(pldm_entity_node *curr,
-					     pldm_pdr *repo)
+					     pldm_pdr *repo, bool is_remote)
 {
 	uint8_t num_logical_children =
 	    pldm_entity_get_num_children(curr, PLDM_ENTITY_ASSOCIAION_LOGICAL);
@@ -555,7 +565,7 @@
 		    (num_logical_children * sizeof(pldm_entity));
 		_entity_association_pdr_add_entry(
 		    curr, repo, logical_pdr_size, num_logical_children,
-		    PLDM_ENTITY_ASSOCIAION_LOGICAL);
+		    PLDM_ENTITY_ASSOCIAION_LOGICAL, is_remote);
 	}
 
 	if (num_physical_children) {
@@ -565,27 +575,28 @@
 		    (num_physical_children * sizeof(pldm_entity));
 		_entity_association_pdr_add_entry(
 		    curr, repo, physical_pdr_size, num_physical_children,
-		    PLDM_ENTITY_ASSOCIAION_PHYSICAL);
+		    PLDM_ENTITY_ASSOCIAION_PHYSICAL, is_remote);
 	}
 }
 
-static void entity_association_pdr_add(pldm_entity_node *curr, pldm_pdr *repo)
+static void entity_association_pdr_add(pldm_entity_node *curr, pldm_pdr *repo,
+				       bool is_remote)
 {
 	if (curr == NULL) {
 		return;
 	}
-	entity_association_pdr_add_entry(curr, repo);
-	entity_association_pdr_add(curr->next_sibling, repo);
-	entity_association_pdr_add(curr->first_child, repo);
+	entity_association_pdr_add_entry(curr, repo, is_remote);
+	entity_association_pdr_add(curr->next_sibling, repo, is_remote);
+	entity_association_pdr_add(curr->first_child, repo, is_remote);
 }
 
 void pldm_entity_association_pdr_add(pldm_entity_association_tree *tree,
-				     pldm_pdr *repo)
+				     pldm_pdr *repo, bool is_remote)
 {
 	assert(tree != NULL);
 	assert(repo != NULL);
 
-	entity_association_pdr_add(tree->root, repo);
+	entity_association_pdr_add(tree->root, repo, is_remote);
 }
 
 void entity_association_tree_find(pldm_entity_node *node, pldm_entity *entity,
diff --git a/libpldm/pdr.h b/libpldm/pdr.h
index c48a559..16ceb55 100644
--- a/libpldm/pdr.h
+++ b/libpldm/pdr.h
@@ -64,11 +64,12 @@
  *  @param[in] size - size of input PDR record in bytes
  *  @param[in] record_handle - record handle of input PDR record; if this is set
  *  to 0, then a record handle is computed and assigned to this PDR record
+ *  @param[in] is_remote - if true, then the PDR is not from this terminus
  *
  *  @return uint32_t - record handle assigned to PDR record
  */
 uint32_t pldm_pdr_add(pldm_pdr *repo, const uint8_t *data, uint32_t size,
-		      uint32_t record_handle);
+		      uint32_t record_handle, bool is_remote);
 
 /** @brief Get record handle of a PDR record
  *
@@ -135,6 +136,8 @@
 			     const pldm_pdr_record *curr_record, uint8_t **data,
 			     uint32_t *size);
 
+bool pldm_pdr_record_is_remote(const pldm_pdr_record *record);
+
 /* ======================= */
 /* FRU Record Set PDR APIs */
 /* ======================= */
@@ -253,9 +256,10 @@
  *
  *  @param[in] tree - opaque pointer to entity association tree
  *  @param[in] repo - PDR repo where entity association records should be added
+ *  @param[in] is_remote - if true, then the PDR is not from this terminus
  */
 void pldm_entity_association_pdr_add(pldm_entity_association_tree *tree,
-				     pldm_pdr *repo);
+				     pldm_pdr *repo, bool is_remote);
 
 /** @brief Get number of children of entity
  *
diff --git a/libpldm/tests/libpldm_pdr_test.cpp b/libpldm/tests/libpldm_pdr_test.cpp
index b09f542..622ec32 100644
--- a/libpldm/tests/libpldm_pdr_test.cpp
+++ b/libpldm/tests/libpldm_pdr_test.cpp
@@ -18,16 +18,17 @@
     auto repo = pldm_pdr_init();
 
     std::array<uint8_t, 10> data{};
-    auto handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    auto handle = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     EXPECT_EQ(handle, 1);
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), data.size());
 
-    handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    handle = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     EXPECT_EQ(handle, 2);
-    handle = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    handle = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     EXPECT_EQ(handle, 3);
-    handle = pldm_pdr_add(repo, data.data(), data.size(), htole32(0xdeeddeed));
+    handle = pldm_pdr_add(repo, data.data(), data.size(), htole32(0xdeeddeed),
+                          false);
     EXPECT_EQ(handle, htole32(0xdeeddeed));
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), data.size() * 4);
@@ -40,7 +41,8 @@
     auto repo = pldm_pdr_init();
 
     std::array<uint32_t, 10> in{100, 345, 3, 6, 89, 0, 11, 45, 23434, 123123};
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1,
+                 false);
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in));
     uint32_t size{};
@@ -71,9 +73,12 @@
 
     std::array<uint32_t, 10> in2{1000, 3450, 30,  60,     890,
                                  0,    110,  450, 234034, 123123};
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2);
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3);
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2,
+                 false);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3,
+                 false);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4,
+                 true);
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in2) * 4);
     hdl = pldm_pdr_find_record(repo, 0, &outData, &size, &nextRecHdl);
@@ -97,12 +102,14 @@
     outData = nullptr;
     hdl = pldm_pdr_find_record(repo, 3, &outData, &size, &nextRecHdl);
     EXPECT_NE(hdl, nullptr);
+    EXPECT_EQ(pldm_pdr_record_is_remote(hdl), false);
     EXPECT_EQ(size, sizeof(in2));
     EXPECT_EQ(nextRecHdl, 4);
     EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
     outData = nullptr;
     hdl = pldm_pdr_find_record(repo, 4, &outData, &size, &nextRecHdl);
     EXPECT_NE(hdl, nullptr);
+    EXPECT_EQ(pldm_pdr_record_is_remote(hdl), true);
     EXPECT_EQ(size, sizeof(in2));
     EXPECT_EQ(nextRecHdl, 0);
     EXPECT_EQ(memcmp(outData, in2.data(), sizeof(in2)), 0);
@@ -116,7 +123,8 @@
     auto repo = pldm_pdr_init();
 
     std::array<uint32_t, 10> in{100, 345, 3, 6, 89, 0, 11, 45, 23434, 123123};
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in.data()), sizeof(in), 1,
+                 false);
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in));
     uint32_t size{};
@@ -131,9 +139,12 @@
 
     std::array<uint32_t, 10> in2{1000, 3450, 30,  60,     890,
                                  0,    110,  450, 234034, 123123};
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2);
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3);
-    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 2,
+                 false);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 3,
+                 false);
+    pldm_pdr_add(repo, reinterpret_cast<uint8_t*>(in2.data()), sizeof(in2), 4,
+                 false);
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
     EXPECT_EQ(pldm_pdr_get_repo_size(repo), sizeof(in2) * 4);
     hdl = pldm_pdr_get_next_record(repo, hdl, &outData, &size, &nextRecHdl);
@@ -165,13 +176,13 @@
     std::array<uint8_t, sizeof(pldm_pdr_hdr)> data{};
     pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(data.data());
     hdr->type = 1;
-    auto first = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    auto first = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     hdr->type = 2;
-    auto second = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    auto second = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     hdr->type = 3;
-    auto third = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    auto third = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
     hdr->type = 4;
-    auto fourth = pldm_pdr_add(repo, data.data(), data.size(), 0);
+    auto fourth = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
 
     uint8_t* outData = nullptr;
     uint32_t size{};
@@ -629,7 +640,7 @@
               1);
 
     auto repo = pldm_pdr_init();
-    pldm_entity_association_pdr_add(tree, repo);
+    pldm_entity_association_pdr_add(tree, repo, false);
 
     EXPECT_EQ(pldm_pdr_get_record_count(repo), 6);
 
diff --git a/libpldmresponder/examples/fru/host_frus.json b/libpldmresponder/examples/fru/host_frus.json
new file mode 100644
index 0000000..07107ff
--- /dev/null
+++ b/libpldmresponder/examples/fru/host_frus.json
@@ -0,0 +1,22 @@
+{
+        "entities":[
+            {
+                # Entity Type 64 from the host has ...
+                "entity_type" : 64,
+                "parent":
+                     {
+                        # ... entity type 100 and instance 1 on the BMC as parent
+                        "entity_type" : 100,
+                        "entity_instance" : 1
+                     }
+            },
+            {
+                "entity_type" : 65,
+                "parent":
+                     {
+                        "entity_type" : 100,
+                        "entity_instance" : 1
+                     }
+            }
+        ]
+}
diff --git a/libpldmresponder/fru.cpp b/libpldmresponder/fru.cpp
index df29065..50e46d8 100644
--- a/libpldmresponder/fru.cpp
+++ b/libpldmresponder/fru.cpp
@@ -104,7 +104,7 @@
         }
     }
 
-    pldm_entity_association_pdr_add(entityTree, pdrRepo);
+    pldm_entity_association_pdr_add(entityTree, pdrRepo, false);
 
     if (table.size())
     {
diff --git a/libpldmresponder/pdr_utils.cpp b/libpldmresponder/pdr_utils.cpp
index 185a6ce..85af37f 100644
--- a/libpldmresponder/pdr_utils.cpp
+++ b/libpldmresponder/pdr_utils.cpp
@@ -17,7 +17,7 @@
 RecordHandle Repo::addRecord(const PdrEntry& pdrEntry)
 {
     return pldm_pdr_add(repo, pdrEntry.data, pdrEntry.size,
-                        pdrEntry.handle.recordHandle);
+                        pdrEntry.handle.recordHandle, false);
 }
 
 const pldm_pdr_record* Repo::getFirstRecord(PdrEntry& pdrEntry)
diff --git a/meson.build b/meson.build
index bb03bc4..23c3b72 100644
--- a/meson.build
+++ b/meson.build
@@ -18,6 +18,7 @@
 conf_data.set_quoted('BIOS_TABLES_DIR', '/var/lib/pldm/bios')
 conf_data.set_quoted('PDR_JSONS_DIR', '/usr/share/pldm/pdr')
 conf_data.set_quoted('FRU_JSONS_DIR', '/usr/share/pldm/fru')
+conf_data.set_quoted('HOST_JSONS_DIR', '/usr/share/pldm/host')
 if get_option('oem-ibm').enabled()
   conf_data.set_quoted('FILE_TABLE_JSON', '/usr/share/pldm/fileTable.json')
   conf_data.set_quoted('LID_PERM_DIR', '/usr/share/host-fw')
diff --git a/pldmd.cpp b/pldmd.cpp
index 030fcb1..eb882f4 100644
--- a/pldmd.cpp
+++ b/pldmd.cpp
@@ -172,7 +172,8 @@
     if (hostEID)
     {
         hostPDRHandler = std::make_unique<HostPDRHandler>(
-            sockfd, hostEID, event, pdrRepo.get(), dbusImplReq);
+            sockfd, hostEID, event, pdrRepo.get(), entityTree.get(),
+            dbusImplReq);
     }
 
     Invoker invoker{};