blob: 7002c797ab688763936d0080072205c70ddb417e [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
John Wang58a0e062019-11-08 15:38:15 +080014namespace pldmtool
15{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050016
John Wang58a0e062019-11-08 15:38:15 +080017namespace helper
18{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050019/*
Sridevi Rameshc91822b2020-02-27 09:26:41 -060020 * print the input buffer if pldm verbosity is enabled.
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050021 *
22 */
Sridevi Rameshc91822b2020-02-27 09:26:41 -060023void printBuffer(const std::vector<uint8_t>& buffer, bool pldmVerbose)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050024{
Sridevi Rameshc91822b2020-02-27 09:26:41 -060025 if (pldmVerbose && !buffer.empty())
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050026 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -060027 std::ostringstream tempStream;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050028 for (int byte : buffer)
29 {
30 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
31 << " ";
32 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060033 std::cout << tempStream.str() << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050034 }
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050035}
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050036/*
37 * Initialize the socket, send pldm command & recieve response from socket
38 *
39 */
40int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
Sridevi Rameshc91822b2020-02-27 09:26:41 -060041 std::vector<uint8_t>& responseMsg, bool pldmVerbose)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050042{
Sridevi Rameshc91822b2020-02-27 09:26:41 -060043
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050044 const char devPath[] = "\0mctp-mux";
45 int returnCode = 0;
46
47 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
48 if (-1 == sockFd)
49 {
50 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060051 std::cerr << "Failed to create the socket : RC = " << sockFd << "\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 creating the socket : RC = ", sockFd);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050055
56 struct sockaddr_un addr
George Liu6492f522020-06-16 10:34:05 +080057 {};
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050058 addr.sun_family = AF_UNIX;
59
60 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
61
62 CustomFD socketFd(sockFd);
63 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
64 sizeof(devPath) + sizeof(addr.sun_family) - 1);
65 if (-1 == result)
66 {
67 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080068 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060069 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050070 return returnCode;
71 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060072 Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050073
74 auto pldmType = MCTP_MSG_TYPE_PLDM;
75 result = write(socketFd(), &pldmType, sizeof(pldmType));
76 if (-1 == result)
77 {
78 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080079 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060080 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050081 return returnCode;
82 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060083 Logger(
84 pldmVerbose,
85 "Success in sending message type as pldm to mctp : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050086
87 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
88 if (-1 == result)
89 {
90 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060091 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050092 return returnCode;
93 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060094 Logger(pldmVerbose, "Write to socket successful : RC = ", result);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050095
96 // Read the response from socket
97 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
98 if (0 == peekedLength)
99 {
John Wang58a0e062019-11-08 15:38:15 +0800100 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -0600101 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500102 return returnCode;
103 }
104 else if (peekedLength <= -1)
105 {
106 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600107 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500108 return returnCode;
109 }
110 else
111 {
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600112 auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
113 do
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500114 {
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500115 ssize_t peekedLength =
116 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500117 responseMsg.resize(peekedLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600118 auto recvDataLength =
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500119 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
120 peekedLength, 0);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600121 auto resphdr =
122 reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
123 if (recvDataLength == peekedLength &&
124 resphdr->instance_id == reqhdr->instance_id &&
125 resphdr->request != PLDM_REQUEST)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500126 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600127 Logger(pldmVerbose, "Total length:", recvDataLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600128 break;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500129 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600130 else if (recvDataLength != peekedLength)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500131 {
John Wang58a0e062019-11-08 15:38:15 +0800132 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600133 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500134 return returnCode;
135 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600136 } while (1);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500137 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800138
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500139 returnCode = shutdown(socketFd(), SHUT_RDWR);
140 if (-1 == returnCode)
141 {
142 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800143 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600144 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500145 return returnCode;
146 }
147
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600148 Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500149 return PLDM_SUCCESS;
150}
John Wang58a0e062019-11-08 15:38:15 +0800151
152void CommandInterface::exec()
153{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600154 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
155 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
156 auto& bus = pldm::utils::DBusHandler::getBus();
157 try
158 {
159 auto service =
160 pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
161 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
162 pldmRequester, "GetInstanceId");
163 method.append(mctp_eid);
164 auto reply = bus.call(method);
165 reply.read(instanceId);
166 }
167 catch (const std::exception& e)
168 {
169 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = " << mctp_eid
170 << ", error = " << e.what() << "\n";
171 return;
172 }
John Wang58a0e062019-11-08 15:38:15 +0800173 auto [rc, requestMsg] = createRequestMsg();
174 if (rc != PLDM_SUCCESS)
175 {
176 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600177 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800178 return;
179 }
180
John Wangb754eee2020-02-15 16:10:25 +0800181 std::vector<uint8_t> responseMsg;
182 rc = pldmSendRecv(requestMsg, responseMsg);
183
184 if (rc != PLDM_SUCCESS)
185 {
186 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
187 return;
188 }
189
190 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
191 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
192}
193
194int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
195 std::vector<uint8_t>& responseMsg)
196{
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600197
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800198 // Insert the PLDM message type and EID at the beginning of the
199 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800200 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800201 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800202
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600203 bool mctpVerbose = pldmVerbose;
204
205 // By default enable request/response msgs for pldmtool raw commands.
206 if (CommandInterface::pldmType == "raw")
207 {
208 pldmVerbose = true;
209 }
210
211 Logger(pldmVerbose, "Request Message:", "");
212 printBuffer(requestMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800213
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800214 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800215 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800216 int fd = pldm_open();
217 if (-1 == fd)
218 {
219 std::cerr << "failed to init mctp "
220 << "\n";
221 return -1;
222 }
223 uint8_t* responseMessage = nullptr;
224 size_t responseMessageSize{};
225 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
226 requestMsg.size() - 2, &responseMessage,
227 &responseMessageSize);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800228
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600229 Logger(pldmVerbose, "Response Message:", "");
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800230 responseMsg.resize(responseMessageSize);
231 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
232
233 free(responseMessage);
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600234 printBuffer(responseMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800235 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800236 else
237 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600238 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
239 Logger(pldmVerbose, "Response Message:", "");
240 printBuffer(responseMsg, pldmVerbose);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800241 responseMsg.erase(responseMsg.begin(),
242 responseMsg.begin() + 2 /* skip the mctp header */);
243 }
John Wangb754eee2020-02-15 16:10:25 +0800244 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800245}
John Wang58a0e062019-11-08 15:38:15 +0800246} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600247} // namespace pldmtool