1 #include "utils.hpp" 2 3 #include <libpldm/entity.h> 4 5 #include <cstdlib> 6 #include <iostream> 7 8 using namespace pldm::utils; 9 10 namespace pldm 11 { 12 namespace hostbmc 13 { 14 namespace utils 15 { 16 Entities getParentEntites(const EntityAssociations& entityAssoc) 17 { 18 Entities parents{}; 19 for (const auto& et : entityAssoc) 20 { 21 parents.push_back(et[0]); 22 } 23 24 bool found = false; 25 for (auto it = parents.begin(); it != parents.end(); 26 it = found ? parents.erase(it) : std::next(it)) 27 { 28 uint16_t parent_contained_id = 29 pldm_entity_node_get_remote_container_id(*it); 30 found = false; 31 for (const auto& evs : entityAssoc) 32 { 33 for (size_t i = 1; i < evs.size() && !found; i++) 34 { 35 uint16_t node_contained_id = 36 pldm_entity_node_get_remote_container_id(evs[i]); 37 38 pldm_entity parent_entity = pldm_entity_extract(*it); 39 pldm_entity node_entity = pldm_entity_extract(evs[i]); 40 41 if (node_entity.entity_type == parent_entity.entity_type && 42 node_entity.entity_instance_num == 43 parent_entity.entity_instance_num && 44 node_contained_id == parent_contained_id) 45 { 46 found = true; 47 } 48 } 49 if (found) 50 { 51 break; 52 } 53 } 54 } 55 56 return parents; 57 } 58 59 void addObjectPathEntityAssociations( 60 const EntityAssociations& entityAssoc, pldm_entity_node* entity, 61 const fs::path& path, ObjectPathMaps& objPathMap, EntityMaps entityMaps, 62 pldm::responder::oem_platform::Handler* oemPlatformHandler) 63 { 64 if (entity == nullptr) 65 { 66 return; 67 } 68 69 bool found = false; 70 pldm_entity node_entity = pldm_entity_extract(entity); 71 if (!entityMaps.contains(node_entity.entity_type)) 72 { 73 // entityMaps doesn't contain entity type which are not required to 74 // build entity object path, so returning from here because this is a 75 // expected behaviour 76 return; 77 } 78 79 std::string entityName = entityMaps.at(node_entity.entity_type); 80 for (const auto& ev : entityAssoc) 81 { 82 pldm_entity ev_entity = pldm_entity_extract(ev[0]); 83 if (ev_entity.entity_instance_num == node_entity.entity_instance_num && 84 ev_entity.entity_type == node_entity.entity_type) 85 { 86 uint16_t node_contained_id = 87 pldm_entity_node_get_remote_container_id(ev[0]); 88 uint16_t entity_contained_id = 89 pldm_entity_node_get_remote_container_id(entity); 90 91 if (node_contained_id != entity_contained_id) 92 { 93 continue; 94 } 95 96 fs::path p = path / fs::path{entityName + 97 std::to_string( 98 node_entity.entity_instance_num)}; 99 std::string entity_path = p.string(); 100 if (oemPlatformHandler) 101 { 102 oemPlatformHandler->updateOemDbusPaths(entity_path); 103 } 104 try 105 { 106 pldm::utils::DBusHandler().getService(entity_path.c_str(), 107 nullptr); 108 // If the entity obtained from the remote PLDM terminal is not 109 // in the MAP, or there is no auxiliary name PDR, add it 110 // directly. Otherwise, check whether the DBus service of 111 // entity_path exists, and overwrite the entity if it does not 112 // exist. 113 if (objPathMap.contains(entity_path)) 114 { 115 objPathMap[entity_path] = entity; 116 } 117 } 118 catch (const std::exception&) 119 { 120 objPathMap[entity_path] = entity; 121 } 122 123 for (size_t i = 1; i < ev.size(); i++) 124 { 125 addObjectPathEntityAssociations(entityAssoc, ev[i], p, 126 objPathMap, entityMaps, 127 oemPlatformHandler); 128 } 129 found = true; 130 } 131 } 132 133 if (!found) 134 { 135 std::string dbusPath = 136 path / fs::path{entityName + 137 std::to_string(node_entity.entity_instance_num)}; 138 if (oemPlatformHandler) 139 { 140 oemPlatformHandler->updateOemDbusPaths(dbusPath); 141 } 142 try 143 { 144 pldm::utils::DBusHandler().getService(dbusPath.c_str(), nullptr); 145 if (objPathMap.contains(dbusPath)) 146 { 147 objPathMap[dbusPath] = entity; 148 } 149 } 150 catch (const std::exception&) 151 { 152 objPathMap[dbusPath] = entity; 153 } 154 } 155 } 156 157 void updateEntityAssociation( 158 const EntityAssociations& entityAssoc, 159 pldm_entity_association_tree* entityTree, ObjectPathMaps& objPathMap, 160 EntityMaps entityMaps, 161 pldm::responder::oem_platform::Handler* oemPlatformHandler) 162 { 163 std::vector<pldm_entity_node*> parentsEntity = 164 getParentEntites(entityAssoc); 165 for (const auto& entity : parentsEntity) 166 { 167 fs::path path{"/xyz/openbmc_project/inventory"}; 168 std::deque<std::string> paths{}; 169 pldm_entity node_entity = pldm_entity_extract(entity); 170 auto node = pldm_entity_association_tree_find_with_locality( 171 entityTree, &node_entity, false); 172 if (!node) 173 { 174 continue; 175 } 176 177 bool found = true; 178 while (node) 179 { 180 if (!pldm_entity_is_exist_parent(node)) 181 { 182 break; 183 } 184 185 pldm_entity parent = pldm_entity_get_parent(node); 186 try 187 { 188 paths.push_back(entityMaps.at(parent.entity_type) + 189 std::to_string(parent.entity_instance_num)); 190 } 191 catch (const std::exception& e) 192 { 193 lg2::error( 194 "Parent entity not found in the entityMaps, type: {ENTITY_TYPE}, num: {NUM}, e: {ERROR}", 195 "ENTITY_TYPE", (int)parent.entity_type, "NUM", 196 (int)parent.entity_instance_num, "ERROR", e); 197 found = false; 198 break; 199 } 200 201 node = pldm_entity_association_tree_find_with_locality( 202 entityTree, &parent, false); 203 } 204 205 if (!found) 206 { 207 continue; 208 } 209 210 while (!paths.empty()) 211 { 212 path = path / fs::path{paths.back()}; 213 paths.pop_back(); 214 } 215 216 addObjectPathEntityAssociations(entityAssoc, entity, path, objPathMap, 217 entityMaps, oemPlatformHandler); 218 } 219 } 220 221 EntityMaps parseEntityMap(const fs::path& filePath) 222 { 223 const Json emptyJson{}; 224 EntityMaps entityMaps{}; 225 std::ifstream jsonFile(filePath); 226 auto data = Json::parse(jsonFile); 227 if (data.is_discarded()) 228 { 229 error("Failed parsing of EntityMap data from json file: '{JSON_PATH}'", 230 "JSON_PATH", filePath); 231 return entityMaps; 232 } 233 auto entities = data.value("EntityTypeToDbusStringMap", emptyJson); 234 char* err; 235 try 236 { 237 std::ranges::transform(entities.items(), 238 std::inserter(entityMaps, entityMaps.begin()), 239 [&err](const auto& element) { 240 std::string key = static_cast<EntityName>(element.key()); 241 return std::make_pair(strtol(key.c_str(), &err, 10), 242 static_cast<EntityName>(element.value())); 243 }); 244 } 245 catch (const std::exception& e) 246 { 247 error( 248 "Failed to create entity to DBus string mapping {ERROR} and Conversion failure is '{ERR}'", 249 "ERROR", e, "ERR", err); 250 } 251 252 return entityMaps; 253 } 254 255 } // namespace utils 256 } // namespace hostbmc 257 } // namespace pldm 258