Mechanism to associate sensor/effecter to FRU entity

The "entity_path" key is defined in PDR JSONs and will have an FRU D-Bus object
path as the value, if this is present, the entity type, instance, and container
id should be associate with the FRU entity.

Tested: test JSON with https://gist.github.com/lxwinspur/7225a9301ccfcbff1f6549203405b4fa
after executing the following command, get the entity information from FruHandler
entity_type = 120
entity_instance_num = 1
entity_container_id = 0

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I019f9a0b9d4dbec20a71dfd797f30ac8f57f67b8
diff --git a/libpldmresponder/examples/pdr/effecter_pdr.json b/libpldmresponder/examples/pdr/effecter_pdr.json
index 316af73..ccdc7ac 100644
--- a/libpldmresponder/examples/pdr/effecter_pdr.json
+++ b/libpldmresponder/examples/pdr/effecter_pdr.json
@@ -4,6 +4,7 @@
       "pdrType": 11,
       "entries": [
         {
+          "entity_path": "/xyz/openbmc_project/foo",
           "type": 33,
           "instance": 0,
           "container": 0,
@@ -49,6 +50,7 @@
           ]
         },
         {
+          "entity_path": "/xyz/openbmc_project/foo",
           "type": 100,
           "instance": 0,
           "container": 0,
@@ -103,6 +105,10 @@
       "pdrType": 9,
       "entries": [
         {
+          "entity_path": "/xyz/openbmc_project/foo",
+          "type": 0,
+          "instance": 0,
+          "container": 0,
           "base_unit": 21,
           "rate_unit": 3,
           "effecter_resolution_init": 1,
diff --git a/libpldmresponder/fru.cpp b/libpldmresponder/fru.cpp
index cb7d5f7..2555a97 100644
--- a/libpldmresponder/fru.cpp
+++ b/libpldmresponder/fru.cpp
@@ -93,6 +93,8 @@
 
                     auto recordInfos = parser.getRecordInfo(interface.first);
                     populateRecords(interfaces, recordInfos, entity);
+
+                    associatedEntityMap.emplace(object.first, entity);
                     break;
                 }
                 catch (const std::exception& e)
diff --git a/libpldmresponder/fru.hpp b/libpldmresponder/fru.hpp
index b19519c..c890a87 100644
--- a/libpldmresponder/fru.hpp
+++ b/libpldmresponder/fru.hpp
@@ -31,6 +31,7 @@
 using InterfaceMap = std::map<Interface, PropertyMap>;
 using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
 using ObjectPath = std::string;
+using AssociatedEntityMap = std::map<ObjectPath, pldm_entity>;
 
 } // namespace dbus
 
@@ -124,6 +125,18 @@
      */
     void buildFRUTable();
 
+    /** @brief Get std::map associated with the entity
+     *         key: object path
+     *         value: pldm_entity
+     *
+     *  @return std::map<ObjectPath, pldm_entity>
+     */
+    inline const pldm::responder::dbus::AssociatedEntityMap&
+        getAssociateEntityMap() const
+    {
+        return associatedEntityMap;
+    }
+
   private:
     uint16_t nextRSI()
     {
@@ -151,9 +164,13 @@
      *  @param[in] recordInfos - FRU record info to build the FRU records
      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
      */
-    void populateRecords(const pldm::responder::dbus::InterfaceMap& interfaces,
+    void populateRecords(const dbus::InterfaceMap& interfaces,
                          const fru_parser::FruRecordInfos& recordInfos,
                          const pldm_entity& entity);
+
+    /** @brief Associate sensor/effecter to FRU entity
+     */
+    dbus::AssociatedEntityMap associatedEntityMap;
 };
 
 namespace fru
@@ -212,6 +229,18 @@
         impl.buildFRUTable();
     }
 
+    /** @brief Get std::map associated with the entity
+     *         key: object path
+     *         value: pldm_entity
+     *
+     *  @return std::map<ObjectPath, pldm_entity>
+     */
+    const pldm::responder::dbus::AssociatedEntityMap&
+        getAssociateEntityMap() const
+    {
+        return impl.getAssociateEntityMap();
+    }
+
     /** @brief Handler for GetFRURecordByOption
      *
      *  @param[in] request - Request message payload
diff --git a/libpldmresponder/pdr_numeric_effecter.hpp b/libpldmresponder/pdr_numeric_effecter.hpp
index 402a426..0258ab2 100644
--- a/libpldmresponder/pdr_numeric_effecter.hpp
+++ b/libpldmresponder/pdr_numeric_effecter.hpp
@@ -47,9 +47,35 @@
 
         pdr->terminus_handle = e.value("terminus_handle", 0);
         pdr->effecter_id = handler.getNextEffecterId();
-        pdr->entity_type = e.value("entity_type", 0);
-        pdr->entity_instance = e.value("entity_instance", 0);
-        pdr->container_id = e.value("container_id", 0);
+
+        try
+        {
+            std::string entity_path = e.value("entity_path", "");
+            auto& associatedEntityMap = handler.getAssociateEntityMap();
+            if (entity_path != "" && associatedEntityMap.find(entity_path) !=
+                                         associatedEntityMap.end())
+            {
+                pdr->entity_type =
+                    associatedEntityMap.at(entity_path).entity_type;
+                pdr->entity_instance =
+                    associatedEntityMap.at(entity_path).entity_instance_num;
+                pdr->container_id =
+                    associatedEntityMap.at(entity_path).entity_container_id;
+            }
+            else
+            {
+                pdr->entity_type = e.value("type", 0);
+                pdr->entity_instance = e.value("instance", 0);
+                pdr->container_id = e.value("container", 0);
+            }
+        }
+        catch (const std::exception& ex)
+        {
+            pdr->entity_type = e.value("type", 0);
+            pdr->entity_instance = e.value("instance", 0);
+            pdr->container_id = e.value("container", 0);
+        }
+
         pdr->effecter_semantic_id = e.value("effecter_semantic_id", 0);
         pdr->effecter_init = e.value("effecter_init", PLDM_NO_INIT);
         pdr->effecter_auxiliary_names = e.value("effecter_init", false);
diff --git a/libpldmresponder/pdr_state_effecter.hpp b/libpldmresponder/pdr_state_effecter.hpp
index 9d10d32..b47686b 100644
--- a/libpldmresponder/pdr_state_effecter.hpp
+++ b/libpldmresponder/pdr_state_effecter.hpp
@@ -65,9 +65,35 @@
 
         pdr->terminus_handle = pdr::BmcPldmTerminusHandle;
         pdr->effecter_id = handler.getNextEffecterId();
-        pdr->entity_type = e.value("type", 0);
-        pdr->entity_instance = e.value("instance", 0);
-        pdr->container_id = e.value("container", 0);
+
+        try
+        {
+            std::string entity_path = e.value("entity_path", "");
+            auto& associatedEntityMap = handler.getAssociateEntityMap();
+            if (entity_path != "" && associatedEntityMap.find(entity_path) !=
+                                         associatedEntityMap.end())
+            {
+                pdr->entity_type =
+                    associatedEntityMap.at(entity_path).entity_type;
+                pdr->entity_instance =
+                    associatedEntityMap.at(entity_path).entity_instance_num;
+                pdr->container_id =
+                    associatedEntityMap.at(entity_path).entity_container_id;
+            }
+            else
+            {
+                pdr->entity_type = e.value("type", 0);
+                pdr->entity_instance = e.value("instance", 0);
+                pdr->container_id = e.value("container", 0);
+            }
+        }
+        catch (const std::exception& ex)
+        {
+            pdr->entity_type = e.value("type", 0);
+            pdr->entity_instance = e.value("instance", 0);
+            pdr->container_id = e.value("container", 0);
+        }
+
         pdr->effecter_semantic_id = 0;
         pdr->effecter_init = PLDM_NO_INIT;
         pdr->has_description_pdr = false;
diff --git a/libpldmresponder/pdr_state_sensor.hpp b/libpldmresponder/pdr_state_sensor.hpp
index f57773a..04b6965 100644
--- a/libpldmresponder/pdr_state_sensor.hpp
+++ b/libpldmresponder/pdr_state_sensor.hpp
@@ -68,9 +68,35 @@
 
         pdr->terminus_handle = 0;
         pdr->sensor_id = handler.getNextSensorId();
-        pdr->entity_type = e.value("type", 0);
-        pdr->entity_instance = e.value("instance", 0);
-        pdr->container_id = e.value("container", 0);
+
+        try
+        {
+            std::string entity_path = e.value("entity_path", "");
+            auto& associatedEntityMap = handler.getAssociateEntityMap();
+            if (entity_path != "" && associatedEntityMap.find(entity_path) !=
+                                         associatedEntityMap.end())
+            {
+                pdr->entity_type =
+                    associatedEntityMap.at(entity_path).entity_type;
+                pdr->entity_instance =
+                    associatedEntityMap.at(entity_path).entity_instance_num;
+                pdr->container_id =
+                    associatedEntityMap.at(entity_path).entity_container_id;
+            }
+            else
+            {
+                pdr->entity_type = e.value("type", 0);
+                pdr->entity_instance = e.value("instance", 0);
+                pdr->container_id = e.value("container", 0);
+            }
+        }
+        catch (const std::exception& ex)
+        {
+            pdr->entity_type = e.value("type", 0);
+            pdr->entity_instance = e.value("instance", 0);
+            pdr->container_id = e.value("container", 0);
+        }
+
         pdr->sensor_init = PLDM_NO_INIT;
         pdr->sensor_auxiliary_names_pdr = false;
         if (sensors.size() > 8)
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index a4d3991..fd6821f 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -2,9 +2,9 @@
 
 #include "config.h"
 
-#include "libpldm/pdr.h"
 #include "libpldm/platform.h"
 #include "libpldm/states.h"
+#include "pdr.h"
 
 #include "common/utils.hpp"
 #include "event_parser.hpp"
@@ -46,6 +46,7 @@
     uint8_t tid, size_t eventDataOffset)>;
 using EventHandlers = std::vector<EventHandler>;
 using EventMap = std::map<EventType, EventHandlers>;
+using AssociatedEntityMap = std::map<DbusPath, pldm_entity>;
 
 // EventEntry = <uint8_t> - EventState <uint8_t> - SensorOffset <uint16_t> -
 // SensorID
@@ -436,6 +437,21 @@
      */
     void generateTerminusLocatorPDR(Repo& repo);
 
+    /** @brief Get std::map associated with the entity
+     *         key: object path
+     *         value: pldm_entity
+     *
+     *  @return std::map<ObjectPath, pldm_entity>
+     */
+    inline const AssociatedEntityMap& getAssociateEntityMap() const
+    {
+        if (fruHandler == nullptr)
+        {
+            throw InternalFailure();
+        }
+        return fruHandler->getAssociateEntityMap();
+    }
+
   private:
     pdr_utils::Repo pdrRepo;
     uint16_t nextEffecterId{};
diff --git a/test/pdr_jsons/state_effecter/good/effecter_pdr.json b/test/pdr_jsons/state_effecter/good/effecter_pdr.json
index ec77f6e..1514a59 100644
--- a/test/pdr_jsons/state_effecter/good/effecter_pdr.json
+++ b/test/pdr_jsons/state_effecter/good/effecter_pdr.json
@@ -4,6 +4,7 @@
             "pdrType": 11,
             "entries": [
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
                     "type": 33,
                     "instance": 0,
                     "container": 0,
@@ -49,6 +50,7 @@
                     ]
                 },
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
                     "type": 100,
                     "instance": 0,
                     "container": 0,
@@ -103,6 +105,10 @@
             "pdrType": 9,
             "entries": [
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 0,
+                    "instance": 0,
+                    "container": 0,
                     "base_unit": 21,
                     "rate_unit": 3,
                     "effecter_resolution_init": 1,
diff --git a/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json b/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json
index d6b0213..826e27a 100644
--- a/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json
+++ b/test/pdr_jsons/state_effecter/malformed/effecter_pdr.json
@@ -4,6 +4,7 @@
             "pdrType": 11,
             "entries": [
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
                     "type": 33
                     "instance": 0,
                     "container": 0,
@@ -49,6 +50,7 @@
                     ]
                 },
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
                     "type": 100,
                     "instance": 0,
                     "container": 0,
@@ -103,6 +105,10 @@
             "pdrType": 9,
             "entries": [
                 {
+                    "entity_path": "/xyz/openbmc_project/foo",
+                    "type": 0,
+                    "instance": 0,
+                    "container": 0,
                     "base_unit": 21,
                     "rate_unit": 3,
                     "effecter_resolution_init": 1,