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 = 97 path / 98 fs::path{entityName + 99 std::to_string(node_entity.entity_instance_num)}; 100 std::string entity_path = p.string(); 101 if (oemPlatformHandler) 102 { 103 oemPlatformHandler->updateOemDbusPaths(entity_path); 104 } 105 try 106 { 107 pldm::utils::DBusHandler().getService(entity_path.c_str(), 108 nullptr); 109 // If the entity obtained from the remote PLDM terminal is not 110 // in the MAP, or there is no auxiliary name PDR, add it 111 // directly. Otherwise, check whether the DBus service of 112 // entity_path exists, and overwrite the entity if it does not 113 // exist. 114 if (objPathMap.contains(entity_path)) 115 { 116 objPathMap[entity_path] = entity; 117 } 118 } 119 catch (const std::exception&) 120 { 121 objPathMap[entity_path] = entity; 122 } 123 124 for (size_t i = 1; i < ev.size(); i++) 125 { 126 addObjectPathEntityAssociations(entityAssoc, ev[i], p, 127 objPathMap, entityMaps, 128 oemPlatformHandler); 129 } 130 found = true; 131 } 132 } 133 134 if (!found) 135 { 136 std::string dbusPath = 137 path / fs::path{entityName + 138 std::to_string(node_entity.entity_instance_num)}; 139 if (oemPlatformHandler) 140 { 141 oemPlatformHandler->updateOemDbusPaths(dbusPath); 142 } 143 try 144 { 145 pldm::utils::DBusHandler().getService(dbusPath.c_str(), nullptr); 146 if (objPathMap.contains(dbusPath)) 147 { 148 objPathMap[dbusPath] = entity; 149 } 150 } 151 catch (const std::exception&) 152 { 153 objPathMap[dbusPath] = entity; 154 } 155 } 156 } 157 158 void updateEntityAssociation( 159 const EntityAssociations& entityAssoc, 160 pldm_entity_association_tree* entityTree, ObjectPathMaps& objPathMap, 161 EntityMaps entityMaps, 162 pldm::responder::oem_platform::Handler* oemPlatformHandler) 163 { 164 std::vector<pldm_entity_node*> parentsEntity = 165 getParentEntites(entityAssoc); 166 for (const auto& entity : parentsEntity) 167 { 168 fs::path path{"/xyz/openbmc_project/inventory"}; 169 std::deque<std::string> paths{}; 170 pldm_entity node_entity = pldm_entity_extract(entity); 171 auto node = pldm_entity_association_tree_find_with_locality( 172 entityTree, &node_entity, false); 173 if (!node) 174 { 175 continue; 176 } 177 178 bool found = true; 179 while (node) 180 { 181 if (!pldm_entity_is_exist_parent(node)) 182 { 183 break; 184 } 185 186 pldm_entity parent = pldm_entity_get_parent(node); 187 try 188 { 189 paths.push_back(entityMaps.at(parent.entity_type) + 190 std::to_string(parent.entity_instance_num)); 191 } 192 catch (const std::exception& e) 193 { 194 lg2::error( 195 "Parent entity not found in the entityMaps, type: {ENTITY_TYPE}, num: {NUM}, e: {ERROR}", 196 "ENTITY_TYPE", (int)parent.entity_type, "NUM", 197 (int)parent.entity_instance_num, "ERROR", e); 198 found = false; 199 break; 200 } 201 202 node = pldm_entity_association_tree_find_with_locality( 203 entityTree, &parent, false); 204 } 205 206 if (!found) 207 { 208 continue; 209 } 210 211 while (!paths.empty()) 212 { 213 path = path / fs::path{paths.back()}; 214 paths.pop_back(); 215 } 216 217 addObjectPathEntityAssociations(entityAssoc, entity, path, objPathMap, 218 entityMaps, oemPlatformHandler); 219 } 220 } 221 222 EntityMaps parseEntityMap(const fs::path& filePath) 223 { 224 const Json emptyJson{}; 225 EntityMaps entityMaps{}; 226 std::ifstream jsonFile(filePath); 227 auto data = Json::parse(jsonFile); 228 if (data.is_discarded()) 229 { 230 error("Failed parsing of EntityMap data from json file: '{JSON_PATH}'", 231 "JSON_PATH", filePath); 232 return entityMaps; 233 } 234 auto entities = data.value("EntityTypeToDbusStringMap", emptyJson); 235 char* err; 236 try 237 { 238 std::ranges::transform( 239 entities.items(), std::inserter(entityMaps, entityMaps.begin()), 240 [&err](const auto& element) { 241 std::string key = static_cast<EntityName>(element.key()); 242 return std::make_pair(strtol(key.c_str(), &err, 10), 243 static_cast<EntityName>(element.value())); 244 }); 245 } 246 catch (const std::exception& e) 247 { 248 error( 249 "Failed to create entity to DBus string mapping {ERROR} and Conversion failure is '{ERR}'", 250 "ERROR", e, "ERR", err); 251 } 252 253 return entityMaps; 254 } 255 256 } // namespace utils 257 } // namespace hostbmc 258 } // namespace pldm 259