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 {
getParentEntites(const EntityAssociations & entityAssoc)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
addObjectPathEntityAssociations(const EntityAssociations & entityAssoc,pldm_entity_node * entity,const fs::path & path,ObjectPathMaps & objPathMap,EntityMaps entityMaps,pldm::responder::oem_platform::Handler * oemPlatformHandler)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
updateEntityAssociation(const EntityAssociations & entityAssoc,pldm_entity_association_tree * entityTree,ObjectPathMaps & objPathMap,EntityMaps entityMaps,pldm::responder::oem_platform::Handler * oemPlatformHandler)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
parseEntityMap(const fs::path & filePath)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