1 #include "utils.hpp"
2
3 #include "common/utils.hpp"
4
5 #include <libpldm/base.h>
6 #include <libpldm/platform.h>
7 #include <sys/socket.h>
8 #include <sys/types.h>
9 #include <sys/un.h>
10 #include <unistd.h>
11
12 #include <phosphor-logging/lg2.hpp>
13 #include <xyz/openbmc_project/Inventory/Decorator/Asset/client.hpp>
14 #include <xyz/openbmc_project/Inventory/Item/Connector/client.hpp>
15 #include <xyz/openbmc_project/ObjectMapper/client.hpp>
16
17 PHOSPHOR_LOG2_USING;
18
19 using namespace pldm::utils;
20
21 namespace pldm
22 {
23 namespace responder
24 {
25 namespace utils
26 {
setupUnixSocket(const std::string & socketInterface)27 int setupUnixSocket(const std::string& socketInterface)
28 {
29 int sock;
30 struct sockaddr_un addr;
31 memset(&addr, 0, sizeof(addr));
32 addr.sun_family = AF_UNIX;
33 size_t interfaceLength =
34 strnlen(socketInterface.c_str(), sizeof(addr.sun_path));
35 if (interfaceLength == sizeof(addr.sun_path))
36 {
37 error("Setup unix socket path '{PATH}' is too long '{LENGTH}'", "PATH",
38 socketInterface, "LENGTH", interfaceLength);
39 return -1;
40 }
41
42 strncpy(addr.sun_path, socketInterface.c_str(), sizeof(addr.sun_path) - 1);
43
44 if ((sock = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1)
45 {
46 error("Failed to open unix socket");
47 return -1;
48 }
49
50 if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
51 {
52 error("Failed to bind unix socket, error number - {ERROR_NUM}",
53 "ERROR_NUM", errno);
54 close(sock);
55 return -1;
56 }
57
58 if (listen(sock, 1) == -1)
59 {
60 error("Failed listen() call while setting up unix socket");
61 close(sock);
62 return -1;
63 }
64
65 fd_set rfd;
66 struct timeval tv;
67 tv.tv_sec = 1;
68 tv.tv_usec = 0;
69
70 FD_ZERO(&rfd);
71 FD_SET(sock, &rfd);
72 int nfd = sock + 1;
73 int fd = -1;
74
75 int retval = select(nfd, &rfd, NULL, NULL, &tv);
76 if (retval < 0)
77 {
78 error(
79 "Failed select() call while setting up unix socket, error number - {ERROR_NUM}",
80 "ERROR_NUM", errno);
81 close(sock);
82 return -1;
83 }
84
85 if ((retval > 0) && (FD_ISSET(sock, &rfd)))
86 {
87 fd = accept(sock, NULL, NULL);
88 if (fd < 0)
89 {
90 error(
91 "Failed accept() call while setting up unix socket, error number - {ERROR_NUM}",
92 "ERROR_NUM", errno);
93 close(sock);
94 return -1;
95 }
96 close(sock);
97 }
98 return fd;
99 }
100
writeToUnixSocket(const int sock,const char * buf,const uint64_t blockSize)101 int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize)
102 {
103 uint64_t i;
104 int nwrite = 0;
105
106 for (i = 0; i < blockSize; i = i + nwrite)
107 {
108 fd_set wfd;
109 struct timeval tv;
110 tv.tv_sec = 1;
111 tv.tv_usec = 0;
112
113 FD_ZERO(&wfd);
114 FD_SET(sock, &wfd);
115 int nfd = sock + 1;
116
117 int retval = select(nfd, NULL, &wfd, NULL, &tv);
118 if (retval < 0)
119 {
120 error(
121 "Failed to write to unix socket select, error number - {ERROR_NUM}",
122 "ERROR_NUM", errno);
123 close(sock);
124 return -1;
125 }
126 if (retval == 0)
127 {
128 nwrite = 0;
129 continue;
130 }
131 if ((retval > 0) && (FD_ISSET(sock, &wfd)))
132 {
133 nwrite = write(sock, buf + i, blockSize - i);
134 if (nwrite < 0)
135 {
136 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
137 {
138 error(
139 "Failed to write to unix socket, error number - {ERROR_NUM}",
140 "ERROR_NUM", errno);
141 nwrite = 0;
142 continue;
143 }
144 error(
145 "Failed to write to unix socket, error number - {ERROR_NUM}",
146 "ERROR_NUM", errno);
147 close(sock);
148 return -1;
149 }
150 }
151 else
152 {
153 nwrite = 0;
154 }
155 }
156 return 0;
157 }
158
checkIfIBMFru(const std::string & objPath)159 bool checkIfIBMFru(const std::string& objPath)
160 {
161 using DecoratorAsset =
162 sdbusplus::client::xyz::openbmc_project::inventory::decorator::Asset<>;
163
164 try
165 {
166 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant(
167 objPath.c_str(), "Model", DecoratorAsset::interface);
168 const auto& model = std::get<std::string>(propVal);
169 if (!model.empty())
170 {
171 return true;
172 }
173 }
174 catch (const std::exception&)
175 {
176 return false;
177 }
178 return false;
179 }
180
findPortObjects(const std::string & adapterObjPath)181 std::vector<std::string> findPortObjects(const std::string& adapterObjPath)
182 {
183 using ItemConnector =
184 sdbusplus::client::xyz::openbmc_project::inventory::item::Connector<>;
185
186 std::vector<std::string> portObjects;
187 try
188 {
189 portObjects = pldm::utils::DBusHandler().getSubTreePaths(
190 adapterObjPath, 0,
191 std::vector<std::string>({ItemConnector::interface}));
192 }
193 catch (const std::exception& e)
194 {
195 error("No ports under adapter '{ADAPTER_OBJ_PATH}' - {ERROR}.",
196 "ADAPTER_OBJ_PATH", adapterObjPath.c_str(), "ERROR", e);
197 }
198
199 return portObjects;
200 }
201
202 } // namespace utils
203
204 namespace oem_ibm_utils
205 {
206 using namespace pldm::utils;
207
setCoreCount(const EntityAssociations & Associations,const EntityMaps entityMaps)208 int pldm::responder::oem_ibm_utils::Handler::setCoreCount(
209 const EntityAssociations& Associations, const EntityMaps entityMaps)
210 {
211 int coreCountRef = 0;
212 // get the CPU pldm entities
213 for (const auto& entries : Associations)
214 {
215 auto parent = pldm_entity_extract(entries[0]);
216 // entries[0] would be the parent in the entity association map
217 if (parent.entity_type == PLDM_ENTITY_PROC)
218 {
219 int& coreCount = coreCountRef;
220 for (const auto& entry : entries)
221 {
222 auto child = pldm_entity_extract(entry);
223 if (child.entity_type == (PLDM_ENTITY_PROC | 0x8000))
224 {
225 // got a core child
226 ++coreCount;
227 }
228 }
229 try
230 {
231 auto grand_parent = pldm_entity_get_parent(entries[0]);
232 std::string grepWord = std::format(
233 "{}{}/{}{}", entityMaps.at(grand_parent.entity_type),
234 std::to_string(grand_parent.entity_instance_num),
235 entityMaps.at(parent.entity_type),
236 std::to_string(parent.entity_instance_num));
237 static constexpr auto searchpath = "/xyz/openbmc_project/";
238 std::vector<std::string> cpuInterface = {
239 "xyz.openbmc_project.Inventory.Item.Cpu"};
240 pldm::utils::GetSubTreeResponse response = dBusIntf->getSubtree(
241 searchpath, 0 /* depth */, cpuInterface);
242 for (const auto& [objectPath, serviceMap] : response)
243 {
244 // find the object path with first occurrence of coreX
245 if (objectPath.contains(grepWord))
246 {
247 pldm::utils::DBusMapping dbusMapping{
248 objectPath, cpuInterface[0], "CoreCount",
249 "uint16_t"};
250 pldm::utils::PropertyValue value =
251 static_cast<uint16_t>(coreCount);
252 try
253 {
254 dBusIntf->setDbusProperty(dbusMapping, value);
255 }
256 catch (const std::exception& e)
257 {
258 error(
259 "Failed to set the core count property at interface '{INTERFACE}': {ERROR}",
260 "INTERFACE", cpuInterface[0], "ERROR", e);
261 }
262 }
263 }
264 }
265 catch (const std::exception& e)
266 {
267 error("Failed to searching CoreCount property: {ERROR}",
268 "ERROR", e);
269 }
270 }
271 }
272 return coreCountRef;
273 }
274
275 } // namespace oem_ibm_utils
276 } // namespace responder
277 } // namespace pldm
278