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