#include "utils.hpp" #include #include #include 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); } try { pldm::utils::DBusHandler().getService(entity_path.c_str(), nullptr); // 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; } } catch (const std::exception&) { 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); if (objPathMap.contains(dbusPath)) { objPathMap[dbusPath] = entity; } } catch (const std::exception&) { 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 parentsEntity = getParentEntites(entityAssoc); for (const auto& entity : parentsEntity) { fs::path path{"/xyz/openbmc_project/inventory"}; std::deque 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(element.key()); return std::make_pair(strtol(key.c_str(), &err, 10), static_cast(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