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 { 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 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 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 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 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