blob: 17485cd57aa7c97edad5872709f9bbc6edcb0ccd [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
5#include <systemd/sd-bus.h>
6
7#include <exception>
8#include <sdbusplus/server.hpp>
9#include <xyz/openbmc_project/Logging/Entry/server.hpp>
10
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +080011#include "libpldm/requester/pldm.h"
12
John Wang58a0e062019-11-08 15:38:15 +080013namespace pldmtool
14{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050015
John Wang58a0e062019-11-08 15:38:15 +080016namespace helper
17{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050018/*
19 * print the input buffer
20 *
21 */
22void printBuffer(const std::vector<uint8_t>& buffer)
23{
24 std::ostringstream tempStream;
25 if (!buffer.empty())
26 {
27 for (int byte : buffer)
28 {
29 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
30 << " ";
31 }
32 }
John Wang58a0e062019-11-08 15:38:15 +080033 std::cout << tempStream.str() << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050034}
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050035/*
36 * Initialize the socket, send pldm command & recieve response from socket
37 *
38 */
39int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
40 std::vector<uint8_t>& responseMsg)
41{
42 const char devPath[] = "\0mctp-mux";
43 int returnCode = 0;
44
45 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
46 if (-1 == sockFd)
47 {
48 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060049 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050050 return returnCode;
51 }
John Wang58a0e062019-11-08 15:38:15 +080052 std::cout << "Success in creating the socket : RC = " << sockFd
53 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050054
55 struct sockaddr_un addr
56 {
57 };
58 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 }
John Wang58a0e062019-11-08 15:38:15 +080072 std::cout << "Success in connecting to socket : RC = " << returnCode
73 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050074
75 auto pldmType = MCTP_MSG_TYPE_PLDM;
76 result = write(socketFd(), &pldmType, sizeof(pldmType));
77 if (-1 == result)
78 {
79 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080080 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060081 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050082 return returnCode;
83 }
John Wang58a0e062019-11-08 15:38:15 +080084 std::cout << "Success in sending message type as pldm to mctp : RC = "
85 << returnCode << std::endl;
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 }
John Wang58a0e062019-11-08 15:38:15 +080094 std::cout << "Write to socket successful : RC = " << result << std::endl;
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 {
John Wang58a0e062019-11-08 15:38:15 +0800127 std::cout << "Total length: " << recvDataLength << std::endl;
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
John Wang58a0e062019-11-08 15:38:15 +0800148 std::cout << "Shutdown Socket successful : RC = " << returnCode
149 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500150 return PLDM_SUCCESS;
151}
John Wang58a0e062019-11-08 15:38:15 +0800152
153void CommandInterface::exec()
154{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600155 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
156 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
157 auto& bus = pldm::utils::DBusHandler::getBus();
158 try
159 {
160 auto service =
161 pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
162 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
163 pldmRequester, "GetInstanceId");
164 method.append(mctp_eid);
165 auto reply = bus.call(method);
166 reply.read(instanceId);
167 }
168 catch (const std::exception& e)
169 {
170 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = " << mctp_eid
171 << ", error = " << e.what() << "\n";
172 return;
173 }
John Wang58a0e062019-11-08 15:38:15 +0800174 auto [rc, requestMsg] = createRequestMsg();
175 if (rc != PLDM_SUCCESS)
176 {
177 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600178 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800179 return;
180 }
181
182 std::cout << "Encode request successfully" << std::endl;
183
John Wangb754eee2020-02-15 16:10:25 +0800184 std::vector<uint8_t> responseMsg;
185 rc = pldmSendRecv(requestMsg, responseMsg);
186
187 if (rc != PLDM_SUCCESS)
188 {
189 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
190 return;
191 }
192
193 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
194 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
195}
196
197int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
198 std::vector<uint8_t>& responseMsg)
199{
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800200 // Insert the PLDM message type and EID at the beginning of the
201 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800202 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800203 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800204
205 std::cout << "Request Message:" << std::endl;
206 printBuffer(requestMsg);
207
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800208 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800209 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800210 int fd = pldm_open();
211 if (-1 == fd)
212 {
213 std::cerr << "failed to init mctp "
214 << "\n";
215 return -1;
216 }
217 uint8_t* responseMessage = nullptr;
218 size_t responseMessageSize{};
219 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
220 requestMsg.size() - 2, &responseMessage,
221 &responseMessageSize);
222 std::cout << "Response Message:" << std::endl;
223
224 responseMsg.resize(responseMessageSize);
225 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
226
227 free(responseMessage);
228 printBuffer(responseMsg);
John Wang58a0e062019-11-08 15:38:15 +0800229 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800230 else
231 {
232 mctpSockSendRecv(requestMsg, responseMsg);
233 std::cout << "Response Message:" << std::endl;
234 printBuffer(responseMsg);
235 responseMsg.erase(responseMsg.begin(),
236 responseMsg.begin() + 2 /* skip the mctp header */);
237 }
John Wangb754eee2020-02-15 16:10:25 +0800238 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800239}
John Wang58a0e062019-11-08 15:38:15 +0800240} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600241} // namespace pldmtool