blob: 0bb2941a7146a5d9d064710862dc038b8e978a02 [file] [log] [blame]
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05001#include "pldm_cmd_helper.hpp"
2
George Liu6492f522020-06-16 10:34:05 +08003#include "libpldm/requester/pldm.h"
4
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -06005#include "xyz/openbmc_project/Common/error.hpp"
6
7#include <systemd/sd-bus.h>
8
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -06009#include <sdbusplus/server.hpp>
10#include <xyz/openbmc_project/Logging/Entry/server.hpp>
11
George Liu6492f522020-06-16 10:34:05 +080012#include <exception>
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +080013
Brad Bishop5079ac42021-08-19 18:35:06 -040014using namespace pldm::utils;
15
John Wang58a0e062019-11-08 15:38:15 +080016namespace pldmtool
17{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050018
John Wang58a0e062019-11-08 15:38:15 +080019namespace helper
20{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050021/*
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050022 * Initialize the socket, send pldm command & recieve response from socket
23 *
24 */
25int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
Sridevi Rameshc91822b2020-02-27 09:26:41 -060026 std::vector<uint8_t>& responseMsg, bool pldmVerbose)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050027{
Sridevi Rameshc91822b2020-02-27 09:26:41 -060028
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050029 const char devPath[] = "\0mctp-mux";
30 int returnCode = 0;
31
32 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
33 if (-1 == sockFd)
34 {
35 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060036 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050037 return returnCode;
38 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060039 Logger(pldmVerbose, "Success in creating the socket : RC = ", sockFd);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050040
41 struct sockaddr_un addr
George Liu6492f522020-06-16 10:34:05 +080042 {};
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050043 addr.sun_family = AF_UNIX;
44
45 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
46
47 CustomFD socketFd(sockFd);
48 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
49 sizeof(devPath) + sizeof(addr.sun_family) - 1);
50 if (-1 == result)
51 {
52 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080053 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060054 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050055 return returnCode;
56 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060057 Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050058
59 auto pldmType = MCTP_MSG_TYPE_PLDM;
60 result = write(socketFd(), &pldmType, sizeof(pldmType));
61 if (-1 == result)
62 {
63 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080064 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060065 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050066 return returnCode;
67 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060068 Logger(
69 pldmVerbose,
70 "Success in sending message type as pldm to mctp : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050071
72 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
73 if (-1 == result)
74 {
75 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060076 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050077 return returnCode;
78 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060079 Logger(pldmVerbose, "Write to socket successful : RC = ", result);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050080
81 // Read the response from socket
82 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
83 if (0 == peekedLength)
84 {
John Wang58a0e062019-11-08 15:38:15 +080085 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -060086 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050087 return returnCode;
88 }
89 else if (peekedLength <= -1)
90 {
91 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060092 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050093 return returnCode;
94 }
95 else
96 {
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -060097 auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
98 do
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050099 {
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500100 ssize_t peekedLength =
101 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500102 responseMsg.resize(peekedLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600103 auto recvDataLength =
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500104 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
105 peekedLength, 0);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600106 auto resphdr =
107 reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
108 if (recvDataLength == peekedLength &&
109 resphdr->instance_id == reqhdr->instance_id &&
110 resphdr->request != PLDM_REQUEST)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500111 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600112 Logger(pldmVerbose, "Total length:", recvDataLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600113 break;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500114 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600115 else if (recvDataLength != peekedLength)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500116 {
John Wang58a0e062019-11-08 15:38:15 +0800117 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600118 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500119 return returnCode;
120 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600121 } while (1);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500122 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800123
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500124 returnCode = shutdown(socketFd(), SHUT_RDWR);
125 if (-1 == returnCode)
126 {
127 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800128 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600129 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500130 return returnCode;
131 }
132
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600133 Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500134 return PLDM_SUCCESS;
135}
John Wang58a0e062019-11-08 15:38:15 +0800136
137void CommandInterface::exec()
138{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600139 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
140 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
141 auto& bus = pldm::utils::DBusHandler::getBus();
142 try
143 {
144 auto service =
145 pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
146 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
147 pldmRequester, "GetInstanceId");
148 method.append(mctp_eid);
149 auto reply = bus.call(method);
150 reply.read(instanceId);
151 }
152 catch (const std::exception& e)
153 {
154 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = " << mctp_eid
155 << ", error = " << e.what() << "\n";
156 return;
157 }
John Wang58a0e062019-11-08 15:38:15 +0800158 auto [rc, requestMsg] = createRequestMsg();
159 if (rc != PLDM_SUCCESS)
160 {
161 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600162 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800163 return;
164 }
165
John Wangb754eee2020-02-15 16:10:25 +0800166 std::vector<uint8_t> responseMsg;
167 rc = pldmSendRecv(requestMsg, responseMsg);
168
169 if (rc != PLDM_SUCCESS)
170 {
171 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
172 return;
173 }
174
175 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
176 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
177}
178
179int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
180 std::vector<uint8_t>& responseMsg)
181{
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600182
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800183 // Insert the PLDM message type and EID at the beginning of the
184 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800185 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800186 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800187
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600188 bool mctpVerbose = pldmVerbose;
189
190 // By default enable request/response msgs for pldmtool raw commands.
191 if (CommandInterface::pldmType == "raw")
192 {
193 pldmVerbose = true;
194 }
195
196 Logger(pldmVerbose, "Request Message:", "");
197 printBuffer(requestMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800198
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800199 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800200 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800201 int fd = pldm_open();
202 if (-1 == fd)
203 {
204 std::cerr << "failed to init mctp "
205 << "\n";
206 return -1;
207 }
208 uint8_t* responseMessage = nullptr;
209 size_t responseMessageSize{};
Sampa Misra9f8d2b02021-03-24 08:33:14 +0000210 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
211 requestMsg.size() - 2, &responseMessage,
212 &responseMessageSize);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800213
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600214 Logger(pldmVerbose, "Response Message:", "");
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800215 responseMsg.resize(responseMessageSize);
216 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
217
218 free(responseMessage);
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600219 printBuffer(responseMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800220 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800221 else
222 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600223 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
224 Logger(pldmVerbose, "Response Message:", "");
225 printBuffer(responseMsg, pldmVerbose);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800226 responseMsg.erase(responseMsg.begin(),
227 responseMsg.begin() + 2 /* skip the mctp header */);
228 }
John Wangb754eee2020-02-15 16:10:25 +0800229 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800230}
John Wang58a0e062019-11-08 15:38:15 +0800231} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600232} // namespace pldmtool