blob: 510f6df2941821b13c0936544c8126be7444110b [file] [log] [blame]
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05001#include "pldm_cmd_helper.hpp"
2
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -06003#include "xyz/openbmc_project/Common/error.hpp"
4
George Liuc453e162022-12-21 17:16:23 +08005#include <libpldm/pldm.h>
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -06006#include <systemd/sd-bus.h>
7
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -06008#include <sdbusplus/server.hpp>
9#include <xyz/openbmc_project/Logging/Entry/server.hpp>
10
George Liu6492f522020-06-16 10:34:05 +080011#include <exception>
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +080012
Brad Bishop5079ac42021-08-19 18:35:06 -040013using namespace pldm::utils;
14
John Wang58a0e062019-11-08 15:38:15 +080015namespace pldmtool
16{
John Wang58a0e062019-11-08 15:38:15 +080017namespace helper
18{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050019/*
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050020 * Initialize the socket, send pldm command & recieve response from socket
21 *
22 */
23int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
Sridevi Rameshc91822b2020-02-27 09:26:41 -060024 std::vector<uint8_t>& responseMsg, bool pldmVerbose)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050025{
26 const char devPath[] = "\0mctp-mux";
27 int returnCode = 0;
28
29 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
30 if (-1 == sockFd)
31 {
32 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060033 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050034 return returnCode;
35 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060036 Logger(pldmVerbose, "Success in creating the socket : RC = ", sockFd);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050037
38 struct sockaddr_un addr
George Liu6492f522020-06-16 10:34:05 +080039 {};
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050040 addr.sun_family = AF_UNIX;
41
42 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
43
44 CustomFD socketFd(sockFd);
45 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
46 sizeof(devPath) + sizeof(addr.sun_family) - 1);
47 if (-1 == result)
48 {
49 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080050 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060051 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050052 return returnCode;
53 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060054 Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050055
56 auto pldmType = MCTP_MSG_TYPE_PLDM;
57 result = write(socketFd(), &pldmType, sizeof(pldmType));
58 if (-1 == result)
59 {
60 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080061 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060062 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050063 return returnCode;
64 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060065 Logger(
66 pldmVerbose,
67 "Success in sending message type as pldm to mctp : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050068
69 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
70 if (-1 == result)
71 {
72 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060073 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050074 return returnCode;
75 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060076 Logger(pldmVerbose, "Write to socket successful : RC = ", result);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050077
78 // Read the response from socket
79 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
80 if (0 == peekedLength)
81 {
John Wang58a0e062019-11-08 15:38:15 +080082 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -060083 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050084 return returnCode;
85 }
86 else if (peekedLength <= -1)
87 {
88 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060089 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050090 return returnCode;
91 }
92 else
93 {
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -060094 auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
95 do
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050096 {
Patrick Williams6da4f912023-05-10 07:50:53 -050097 ssize_t peekedLength = recv(socketFd(), nullptr, 0,
98 MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050099 responseMsg.resize(peekedLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600100 auto recvDataLength =
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500101 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
102 peekedLength, 0);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600103 auto resphdr =
104 reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
105 if (recvDataLength == peekedLength &&
106 resphdr->instance_id == reqhdr->instance_id &&
107 resphdr->request != PLDM_REQUEST)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500108 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600109 Logger(pldmVerbose, "Total length:", recvDataLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600110 break;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500111 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600112 else if (recvDataLength != peekedLength)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500113 {
John Wang58a0e062019-11-08 15:38:15 +0800114 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600115 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500116 return returnCode;
117 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600118 } while (1);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500119 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800120
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500121 returnCode = shutdown(socketFd(), SHUT_RDWR);
122 if (-1 == returnCode)
123 {
124 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800125 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600126 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500127 return returnCode;
128 }
129
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600130 Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500131 return PLDM_SUCCESS;
132}
John Wang58a0e062019-11-08 15:38:15 +0800133
134void CommandInterface::exec()
135{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600136 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
137 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
138 auto& bus = pldm::utils::DBusHandler::getBus();
139 try
140 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500141 auto service = pldm::utils::DBusHandler().getService(pldmObjPath,
142 pldmRequester);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600143 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
144 pldmRequester, "GetInstanceId");
145 method.append(mctp_eid);
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500146 auto reply = bus.call(method, dbusTimeout);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600147 reply.read(instanceId);
148 }
149 catch (const std::exception& e)
150 {
Manojkiran Eda0a725f82021-10-23 06:02:26 +0530151 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = "
152 << (unsigned)mctp_eid << ", error = " << e.what() << "\n";
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600153 return;
154 }
John Wang58a0e062019-11-08 15:38:15 +0800155 auto [rc, requestMsg] = createRequestMsg();
156 if (rc != PLDM_SUCCESS)
157 {
158 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600159 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800160 return;
161 }
162
John Wangb754eee2020-02-15 16:10:25 +0800163 std::vector<uint8_t> responseMsg;
164 rc = pldmSendRecv(requestMsg, responseMsg);
165
166 if (rc != PLDM_SUCCESS)
167 {
168 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
169 return;
170 }
171
172 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
173 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
174}
175
176int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
177 std::vector<uint8_t>& responseMsg)
178{
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800179 // Insert the PLDM message type and EID at the beginning of the
180 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800181 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800182 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800183
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600184 bool mctpVerbose = pldmVerbose;
185
186 // By default enable request/response msgs for pldmtool raw commands.
187 if (CommandInterface::pldmType == "raw")
188 {
189 pldmVerbose = true;
190 }
191
Tom Josephe5268cd2021-09-07 13:04:03 +0530192 if (pldmVerbose)
193 {
194 std::cout << "pldmtool: ";
195 printBuffer(Tx, requestMsg);
196 }
John Wang58a0e062019-11-08 15:38:15 +0800197
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800198 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800199 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800200 int fd = pldm_open();
201 if (-1 == fd)
202 {
203 std::cerr << "failed to init mctp "
204 << "\n";
205 return -1;
206 }
207 uint8_t* responseMessage = nullptr;
208 size_t responseMessageSize{};
Sampa Misra9f8d2b02021-03-24 08:33:14 +0000209 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
210 requestMsg.size() - 2, &responseMessage,
211 &responseMessageSize);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800212
213 responseMsg.resize(responseMessageSize);
214 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
215
Dung Cao2b85d782022-05-24 09:28:48 +0000216 shutdown(fd, SHUT_RDWR);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800217 free(responseMessage);
Dung Cao2b85d782022-05-24 09:28:48 +0000218
Tom Josephe5268cd2021-09-07 13:04:03 +0530219 if (pldmVerbose)
220 {
221 std::cout << "pldmtool: ";
222 printBuffer(Rx, responseMsg);
223 }
John Wang58a0e062019-11-08 15:38:15 +0800224 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800225 else
226 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600227 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
Tom Josephe5268cd2021-09-07 13:04:03 +0530228 if (pldmVerbose)
229 {
230 std::cout << "pldmtool: ";
231 printBuffer(Rx, responseMsg);
232 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800233 responseMsg.erase(responseMsg.begin(),
234 responseMsg.begin() + 2 /* skip the mctp header */);
235 }
John Wangb754eee2020-02-15 16:10:25 +0800236 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800237}
John Wang58a0e062019-11-08 15:38:15 +0800238} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600239} // namespace pldmtool