xref: /openbmc/pldm/host-bmc/utils.cpp (revision 16c2a0a03e5daac77e204eb99e00711490fb6e26)
17d427f16SKamalkumar Patel #include "utils.hpp"
24e69d252SKamalkumar Patel 
341ca40dcSAndrew Jeffery #include <libpldm/entity.h>
44e69d252SKamalkumar Patel 
5516122e0SKamalkumar Patel #include <cstdlib>
64e69d252SKamalkumar Patel #include <iostream>
74e69d252SKamalkumar Patel 
87d427f16SKamalkumar Patel using namespace pldm::utils;
97d427f16SKamalkumar Patel 
104e69d252SKamalkumar Patel namespace pldm
114e69d252SKamalkumar Patel {
124e69d252SKamalkumar Patel namespace hostbmc
134e69d252SKamalkumar Patel {
144e69d252SKamalkumar Patel namespace utils
154e69d252SKamalkumar Patel {
getParentEntites(const EntityAssociations & entityAssoc)164e69d252SKamalkumar Patel Entities getParentEntites(const EntityAssociations& entityAssoc)
174e69d252SKamalkumar Patel {
184e69d252SKamalkumar Patel     Entities parents{};
194e69d252SKamalkumar Patel     for (const auto& et : entityAssoc)
204e69d252SKamalkumar Patel     {
214e69d252SKamalkumar Patel         parents.push_back(et[0]);
224e69d252SKamalkumar Patel     }
234e69d252SKamalkumar Patel 
244e69d252SKamalkumar Patel     bool found = false;
254e69d252SKamalkumar Patel     for (auto it = parents.begin(); it != parents.end();
264e69d252SKamalkumar Patel          it = found ? parents.erase(it) : std::next(it))
274e69d252SKamalkumar Patel     {
284e69d252SKamalkumar Patel         uint16_t parent_contained_id =
294e69d252SKamalkumar Patel             pldm_entity_node_get_remote_container_id(*it);
304e69d252SKamalkumar Patel         found = false;
314e69d252SKamalkumar Patel         for (const auto& evs : entityAssoc)
324e69d252SKamalkumar Patel         {
334e69d252SKamalkumar Patel             for (size_t i = 1; i < evs.size() && !found; i++)
344e69d252SKamalkumar Patel             {
354e69d252SKamalkumar Patel                 uint16_t node_contained_id =
364e69d252SKamalkumar Patel                     pldm_entity_node_get_remote_container_id(evs[i]);
374e69d252SKamalkumar Patel 
384e69d252SKamalkumar Patel                 pldm_entity parent_entity = pldm_entity_extract(*it);
394e69d252SKamalkumar Patel                 pldm_entity node_entity = pldm_entity_extract(evs[i]);
404e69d252SKamalkumar Patel 
414e69d252SKamalkumar Patel                 if (node_entity.entity_type == parent_entity.entity_type &&
424e69d252SKamalkumar Patel                     node_entity.entity_instance_num ==
434e69d252SKamalkumar Patel                         parent_entity.entity_instance_num &&
444e69d252SKamalkumar Patel                     node_contained_id == parent_contained_id)
454e69d252SKamalkumar Patel                 {
464e69d252SKamalkumar Patel                     found = true;
474e69d252SKamalkumar Patel                 }
484e69d252SKamalkumar Patel             }
494e69d252SKamalkumar Patel             if (found)
504e69d252SKamalkumar Patel             {
514e69d252SKamalkumar Patel                 break;
524e69d252SKamalkumar Patel             }
534e69d252SKamalkumar Patel         }
544e69d252SKamalkumar Patel     }
554e69d252SKamalkumar Patel 
564e69d252SKamalkumar Patel     return parents;
574e69d252SKamalkumar Patel }
584e69d252SKamalkumar Patel 
addObjectPathEntityAssociations(const EntityAssociations & entityAssoc,pldm_entity_node * entity,const fs::path & path,ObjectPathMaps & objPathMap,EntityMaps entityMaps,pldm::responder::oem_platform::Handler * oemPlatformHandler)5915ce5a18SKamalkumar Patel void addObjectPathEntityAssociations(
6015ce5a18SKamalkumar Patel     const EntityAssociations& entityAssoc, pldm_entity_node* entity,
6115ce5a18SKamalkumar Patel     const fs::path& path, ObjectPathMaps& objPathMap, EntityMaps entityMaps,
6215ce5a18SKamalkumar Patel     pldm::responder::oem_platform::Handler* oemPlatformHandler)
634e69d252SKamalkumar Patel {
644e69d252SKamalkumar Patel     if (entity == nullptr)
654e69d252SKamalkumar Patel     {
664e69d252SKamalkumar Patel         return;
674e69d252SKamalkumar Patel     }
684e69d252SKamalkumar Patel 
694e69d252SKamalkumar Patel     bool found = false;
704e69d252SKamalkumar Patel     pldm_entity node_entity = pldm_entity_extract(entity);
714e69d252SKamalkumar Patel     if (!entityMaps.contains(node_entity.entity_type))
724e69d252SKamalkumar Patel     {
73d06de1cbSKamalkumar Patel         // entityMaps doesn't contain entity type which are not required to
74d06de1cbSKamalkumar Patel         // build entity object path, so returning from here because this is a
75d06de1cbSKamalkumar Patel         // expected behaviour
764e69d252SKamalkumar Patel         return;
774e69d252SKamalkumar Patel     }
784e69d252SKamalkumar Patel 
794e69d252SKamalkumar Patel     std::string entityName = entityMaps.at(node_entity.entity_type);
804e69d252SKamalkumar Patel     for (const auto& ev : entityAssoc)
814e69d252SKamalkumar Patel     {
824e69d252SKamalkumar Patel         pldm_entity ev_entity = pldm_entity_extract(ev[0]);
834e69d252SKamalkumar Patel         if (ev_entity.entity_instance_num == node_entity.entity_instance_num &&
844e69d252SKamalkumar Patel             ev_entity.entity_type == node_entity.entity_type)
854e69d252SKamalkumar Patel         {
864e69d252SKamalkumar Patel             uint16_t node_contained_id =
874e69d252SKamalkumar Patel                 pldm_entity_node_get_remote_container_id(ev[0]);
884e69d252SKamalkumar Patel             uint16_t entity_contained_id =
894e69d252SKamalkumar Patel                 pldm_entity_node_get_remote_container_id(entity);
904e69d252SKamalkumar Patel 
914e69d252SKamalkumar Patel             if (node_contained_id != entity_contained_id)
924e69d252SKamalkumar Patel             {
934e69d252SKamalkumar Patel                 continue;
944e69d252SKamalkumar Patel             }
954e69d252SKamalkumar Patel 
96*16c2a0a0SPatrick Williams             fs::path p =
97*16c2a0a0SPatrick Williams                 path /
98*16c2a0a0SPatrick Williams                 fs::path{entityName +
99*16c2a0a0SPatrick Williams                          std::to_string(node_entity.entity_instance_num)};
1004e69d252SKamalkumar Patel             std::string entity_path = p.string();
10115ce5a18SKamalkumar Patel             if (oemPlatformHandler)
10215ce5a18SKamalkumar Patel             {
10315ce5a18SKamalkumar Patel                 oemPlatformHandler->updateOemDbusPaths(entity_path);
10415ce5a18SKamalkumar Patel             }
1054e69d252SKamalkumar Patel             try
1064e69d252SKamalkumar Patel             {
1074e69d252SKamalkumar Patel                 pldm::utils::DBusHandler().getService(entity_path.c_str(),
1084e69d252SKamalkumar Patel                                                       nullptr);
109267c7efcSKamalkumar Patel                 // If the entity obtained from the remote PLDM terminal is not
110267c7efcSKamalkumar Patel                 // in the MAP, or there is no auxiliary name PDR, add it
111267c7efcSKamalkumar Patel                 // directly. Otherwise, check whether the DBus service of
112267c7efcSKamalkumar Patel                 // entity_path exists, and overwrite the entity if it does not
113267c7efcSKamalkumar Patel                 // exist.
114267c7efcSKamalkumar Patel                 if (objPathMap.contains(entity_path))
1154e69d252SKamalkumar Patel                 {
1164e69d252SKamalkumar Patel                     objPathMap[entity_path] = entity;
1174e69d252SKamalkumar Patel                 }
1184e69d252SKamalkumar Patel             }
119267c7efcSKamalkumar Patel             catch (const std::exception&)
120267c7efcSKamalkumar Patel             {
121267c7efcSKamalkumar Patel                 objPathMap[entity_path] = entity;
122267c7efcSKamalkumar Patel             }
1234e69d252SKamalkumar Patel 
1244e69d252SKamalkumar Patel             for (size_t i = 1; i < ev.size(); i++)
1254e69d252SKamalkumar Patel             {
1264e69d252SKamalkumar Patel                 addObjectPathEntityAssociations(entityAssoc, ev[i], p,
12715ce5a18SKamalkumar Patel                                                 objPathMap, entityMaps,
12815ce5a18SKamalkumar Patel                                                 oemPlatformHandler);
1294e69d252SKamalkumar Patel             }
1304e69d252SKamalkumar Patel             found = true;
1314e69d252SKamalkumar Patel         }
1324e69d252SKamalkumar Patel     }
1334e69d252SKamalkumar Patel 
1344e69d252SKamalkumar Patel     if (!found)
1354e69d252SKamalkumar Patel     {
1364e69d252SKamalkumar Patel         std::string dbusPath =
1374e69d252SKamalkumar Patel             path / fs::path{entityName +
1384e69d252SKamalkumar Patel                             std::to_string(node_entity.entity_instance_num)};
13915ce5a18SKamalkumar Patel         if (oemPlatformHandler)
14015ce5a18SKamalkumar Patel         {
14115ce5a18SKamalkumar Patel             oemPlatformHandler->updateOemDbusPaths(dbusPath);
14215ce5a18SKamalkumar Patel         }
1434e69d252SKamalkumar Patel         try
1444e69d252SKamalkumar Patel         {
1454e69d252SKamalkumar Patel             pldm::utils::DBusHandler().getService(dbusPath.c_str(), nullptr);
146267c7efcSKamalkumar Patel             if (objPathMap.contains(dbusPath))
147267c7efcSKamalkumar Patel             {
148267c7efcSKamalkumar Patel                 objPathMap[dbusPath] = entity;
1494e69d252SKamalkumar Patel             }
150267c7efcSKamalkumar Patel         }
151267c7efcSKamalkumar Patel         catch (const std::exception&)
1524e69d252SKamalkumar Patel         {
1534e69d252SKamalkumar Patel             objPathMap[dbusPath] = entity;
1544e69d252SKamalkumar Patel         }
1554e69d252SKamalkumar Patel     }
1564e69d252SKamalkumar Patel }
1574e69d252SKamalkumar Patel 
updateEntityAssociation(const EntityAssociations & entityAssoc,pldm_entity_association_tree * entityTree,ObjectPathMaps & objPathMap,EntityMaps entityMaps,pldm::responder::oem_platform::Handler * oemPlatformHandler)15815ce5a18SKamalkumar Patel void updateEntityAssociation(
15915ce5a18SKamalkumar Patel     const EntityAssociations& entityAssoc,
16015ce5a18SKamalkumar Patel     pldm_entity_association_tree* entityTree, ObjectPathMaps& objPathMap,
16115ce5a18SKamalkumar Patel     EntityMaps entityMaps,
16215ce5a18SKamalkumar Patel     pldm::responder::oem_platform::Handler* oemPlatformHandler)
1634e69d252SKamalkumar Patel {
1644e69d252SKamalkumar Patel     std::vector<pldm_entity_node*> parentsEntity =
1654e69d252SKamalkumar Patel         getParentEntites(entityAssoc);
1664e69d252SKamalkumar Patel     for (const auto& entity : parentsEntity)
1674e69d252SKamalkumar Patel     {
1684e69d252SKamalkumar Patel         fs::path path{"/xyz/openbmc_project/inventory"};
1694e69d252SKamalkumar Patel         std::deque<std::string> paths{};
1704e69d252SKamalkumar Patel         pldm_entity node_entity = pldm_entity_extract(entity);
1714e69d252SKamalkumar Patel         auto node = pldm_entity_association_tree_find_with_locality(
1724e69d252SKamalkumar Patel             entityTree, &node_entity, false);
1734e69d252SKamalkumar Patel         if (!node)
1744e69d252SKamalkumar Patel         {
1754e69d252SKamalkumar Patel             continue;
1764e69d252SKamalkumar Patel         }
1774e69d252SKamalkumar Patel 
1784e69d252SKamalkumar Patel         bool found = true;
1794e69d252SKamalkumar Patel         while (node)
1804e69d252SKamalkumar Patel         {
1814e69d252SKamalkumar Patel             if (!pldm_entity_is_exist_parent(node))
1824e69d252SKamalkumar Patel             {
1834e69d252SKamalkumar Patel                 break;
1844e69d252SKamalkumar Patel             }
1854e69d252SKamalkumar Patel 
1864e69d252SKamalkumar Patel             pldm_entity parent = pldm_entity_get_parent(node);
1874e69d252SKamalkumar Patel             try
1884e69d252SKamalkumar Patel             {
1894e69d252SKamalkumar Patel                 paths.push_back(entityMaps.at(parent.entity_type) +
1904e69d252SKamalkumar Patel                                 std::to_string(parent.entity_instance_num));
1914e69d252SKamalkumar Patel             }
1924e69d252SKamalkumar Patel             catch (const std::exception& e)
1934e69d252SKamalkumar Patel             {
1944e69d252SKamalkumar Patel                 lg2::error(
1954e69d252SKamalkumar Patel                     "Parent entity not found in the entityMaps, type: {ENTITY_TYPE}, num: {NUM}, e: {ERROR}",
1964e69d252SKamalkumar Patel                     "ENTITY_TYPE", (int)parent.entity_type, "NUM",
1974e69d252SKamalkumar Patel                     (int)parent.entity_instance_num, "ERROR", e);
1984e69d252SKamalkumar Patel                 found = false;
1994e69d252SKamalkumar Patel                 break;
2004e69d252SKamalkumar Patel             }
2014e69d252SKamalkumar Patel 
2024e69d252SKamalkumar Patel             node = pldm_entity_association_tree_find_with_locality(
2034e69d252SKamalkumar Patel                 entityTree, &parent, false);
2044e69d252SKamalkumar Patel         }
2054e69d252SKamalkumar Patel 
2064e69d252SKamalkumar Patel         if (!found)
2074e69d252SKamalkumar Patel         {
2084e69d252SKamalkumar Patel             continue;
2094e69d252SKamalkumar Patel         }
2104e69d252SKamalkumar Patel 
2114e69d252SKamalkumar Patel         while (!paths.empty())
2124e69d252SKamalkumar Patel         {
2134e69d252SKamalkumar Patel             path = path / fs::path{paths.back()};
2144e69d252SKamalkumar Patel             paths.pop_back();
2154e69d252SKamalkumar Patel         }
2164e69d252SKamalkumar Patel 
217516122e0SKamalkumar Patel         addObjectPathEntityAssociations(entityAssoc, entity, path, objPathMap,
21815ce5a18SKamalkumar Patel                                         entityMaps, oemPlatformHandler);
2194e69d252SKamalkumar Patel     }
2204e69d252SKamalkumar Patel }
221516122e0SKamalkumar Patel 
parseEntityMap(const fs::path & filePath)222516122e0SKamalkumar Patel EntityMaps parseEntityMap(const fs::path& filePath)
223516122e0SKamalkumar Patel {
224516122e0SKamalkumar Patel     const Json emptyJson{};
225516122e0SKamalkumar Patel     EntityMaps entityMaps{};
226516122e0SKamalkumar Patel     std::ifstream jsonFile(filePath);
227516122e0SKamalkumar Patel     auto data = Json::parse(jsonFile);
228516122e0SKamalkumar Patel     if (data.is_discarded())
229516122e0SKamalkumar Patel     {
230516122e0SKamalkumar Patel         error("Failed parsing of EntityMap data from json file: '{JSON_PATH}'",
231516122e0SKamalkumar Patel               "JSON_PATH", filePath);
232516122e0SKamalkumar Patel         return entityMaps;
233516122e0SKamalkumar Patel     }
234516122e0SKamalkumar Patel     auto entities = data.value("EntityTypeToDbusStringMap", emptyJson);
235516122e0SKamalkumar Patel     char* err;
236516122e0SKamalkumar Patel     try
237516122e0SKamalkumar Patel     {
238*16c2a0a0SPatrick Williams         std::ranges::transform(
239*16c2a0a0SPatrick Williams             entities.items(), std::inserter(entityMaps, entityMaps.begin()),
240516122e0SKamalkumar Patel             [&err](const auto& element) {
241516122e0SKamalkumar Patel                 std::string key = static_cast<EntityName>(element.key());
242516122e0SKamalkumar Patel                 return std::make_pair(strtol(key.c_str(), &err, 10),
243516122e0SKamalkumar Patel                                       static_cast<EntityName>(element.value()));
244516122e0SKamalkumar Patel             });
245516122e0SKamalkumar Patel     }
246516122e0SKamalkumar Patel     catch (const std::exception& e)
247516122e0SKamalkumar Patel     {
248516122e0SKamalkumar Patel         error(
249516122e0SKamalkumar Patel             "Failed to create entity to DBus string mapping {ERROR} and Conversion failure is '{ERR}'",
250516122e0SKamalkumar Patel             "ERROR", e, "ERR", err);
251516122e0SKamalkumar Patel     }
252516122e0SKamalkumar Patel 
253516122e0SKamalkumar Patel     return entityMaps;
254516122e0SKamalkumar Patel }
255516122e0SKamalkumar Patel 
2564e69d252SKamalkumar Patel } // namespace utils
2574e69d252SKamalkumar Patel } // namespace hostbmc
2584e69d252SKamalkumar Patel } // namespace pldm
259