blob: 78f3df2ee7bbd214f41d9497e4cfe17328e0ebe4 [file] [log] [blame]
#include "utils.hpp"
#include <libpldm/entity.h>
#include <cstdlib>
#include <iostream>
using namespace pldm::utils;
namespace pldm
{
namespace hostbmc
{
namespace utils
{
Entities getParentEntites(const EntityAssociations& entityAssoc)
{
Entities parents{};
for (const auto& et : entityAssoc)
{
parents.push_back(et[0]);
}
bool found = false;
for (auto it = parents.begin(); it != parents.end();
it = found ? parents.erase(it) : std::next(it))
{
uint16_t parent_contained_id =
pldm_entity_node_get_remote_container_id(*it);
found = false;
for (const auto& evs : entityAssoc)
{
for (size_t i = 1; i < evs.size() && !found; i++)
{
uint16_t node_contained_id =
pldm_entity_node_get_remote_container_id(evs[i]);
pldm_entity parent_entity = pldm_entity_extract(*it);
pldm_entity node_entity = pldm_entity_extract(evs[i]);
if (node_entity.entity_type == parent_entity.entity_type &&
node_entity.entity_instance_num ==
parent_entity.entity_instance_num &&
node_contained_id == parent_contained_id)
{
found = true;
}
}
if (found)
{
break;
}
}
}
return parents;
}
void addObjectPathEntityAssociations(
const EntityAssociations& entityAssoc, pldm_entity_node* entity,
const fs::path& path, ObjectPathMaps& objPathMap, EntityMaps entityMaps,
pldm::responder::oem_platform::Handler* oemPlatformHandler)
{
if (entity == nullptr)
{
return;
}
bool found = false;
pldm_entity node_entity = pldm_entity_extract(entity);
if (!entityMaps.contains(node_entity.entity_type))
{
// entityMaps doesn't contain entity type which are not required to
// build entity object path, so returning from here because this is a
// expected behaviour
return;
}
std::string entityName = entityMaps.at(node_entity.entity_type);
for (const auto& ev : entityAssoc)
{
pldm_entity ev_entity = pldm_entity_extract(ev[0]);
if (ev_entity.entity_instance_num == node_entity.entity_instance_num &&
ev_entity.entity_type == node_entity.entity_type)
{
uint16_t node_contained_id =
pldm_entity_node_get_remote_container_id(ev[0]);
uint16_t entity_contained_id =
pldm_entity_node_get_remote_container_id(entity);
if (node_contained_id != entity_contained_id)
{
continue;
}
fs::path p = path / fs::path{entityName +
std::to_string(
node_entity.entity_instance_num)};
std::string entity_path = p.string();
if (oemPlatformHandler)
{
oemPlatformHandler->updateOemDbusPaths(entity_path);
}
// If the entity obtained from the remote PLDM terminal is not in
// the MAP, or there is no auxiliary name PDR, add it directly.
// Otherwise, check whether the DBus service of entity_path exists,
// and overwrite the entity if it does not exist.
if (!objPathMap.contains(entity_path))
{
objPathMap[entity_path] = entity;
}
else
{
try
{
pldm::utils::DBusHandler().getService(entity_path.c_str(),
nullptr);
}
catch (const std::exception& e)
{
objPathMap[entity_path] = entity;
}
}
for (size_t i = 1; i < ev.size(); i++)
{
addObjectPathEntityAssociations(entityAssoc, ev[i], p,
objPathMap, entityMaps,
oemPlatformHandler);
}
found = true;
}
}
if (!found)
{
std::string dbusPath =
path / fs::path{entityName +
std::to_string(node_entity.entity_instance_num)};
if (oemPlatformHandler)
{
oemPlatformHandler->updateOemDbusPaths(dbusPath);
}
try
{
pldm::utils::DBusHandler().getService(dbusPath.c_str(), nullptr);
}
catch (const std::exception& e)
{
objPathMap[dbusPath] = entity;
}
}
}
void updateEntityAssociation(
const EntityAssociations& entityAssoc,
pldm_entity_association_tree* entityTree, ObjectPathMaps& objPathMap,
EntityMaps entityMaps,
pldm::responder::oem_platform::Handler* oemPlatformHandler)
{
std::vector<pldm_entity_node*> parentsEntity =
getParentEntites(entityAssoc);
for (const auto& entity : parentsEntity)
{
fs::path path{"/xyz/openbmc_project/inventory"};
std::deque<std::string> paths{};
pldm_entity node_entity = pldm_entity_extract(entity);
auto node = pldm_entity_association_tree_find_with_locality(
entityTree, &node_entity, false);
if (!node)
{
continue;
}
bool found = true;
while (node)
{
if (!pldm_entity_is_exist_parent(node))
{
break;
}
pldm_entity parent = pldm_entity_get_parent(node);
try
{
paths.push_back(entityMaps.at(parent.entity_type) +
std::to_string(parent.entity_instance_num));
}
catch (const std::exception& e)
{
lg2::error(
"Parent entity not found in the entityMaps, type: {ENTITY_TYPE}, num: {NUM}, e: {ERROR}",
"ENTITY_TYPE", (int)parent.entity_type, "NUM",
(int)parent.entity_instance_num, "ERROR", e);
found = false;
break;
}
node = pldm_entity_association_tree_find_with_locality(
entityTree, &parent, false);
}
if (!found)
{
continue;
}
while (!paths.empty())
{
path = path / fs::path{paths.back()};
paths.pop_back();
}
addObjectPathEntityAssociations(entityAssoc, entity, path, objPathMap,
entityMaps, oemPlatformHandler);
}
}
EntityMaps parseEntityMap(const fs::path& filePath)
{
const Json emptyJson{};
EntityMaps entityMaps{};
std::ifstream jsonFile(filePath);
auto data = Json::parse(jsonFile);
if (data.is_discarded())
{
error("Failed parsing of EntityMap data from json file: '{JSON_PATH}'",
"JSON_PATH", filePath);
return entityMaps;
}
auto entities = data.value("EntityTypeToDbusStringMap", emptyJson);
char* err;
try
{
std::ranges::transform(entities.items(),
std::inserter(entityMaps, entityMaps.begin()),
[&err](const auto& element) {
std::string key = static_cast<EntityName>(element.key());
return std::make_pair(strtol(key.c_str(), &err, 10),
static_cast<EntityName>(element.value()));
});
}
catch (const std::exception& e)
{
error(
"Failed to create entity to DBus string mapping {ERROR} and Conversion failure is '{ERR}'",
"ERROR", e, "ERR", err);
}
return entityMaps;
}
} // namespace utils
} // namespace hostbmc
} // namespace pldm