blob: 10e051fba90b91fe139baa62b777b1330ddc0118 [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/*
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{
Sridevi Rameshc91822b2020-02-27 09:26:41 -060026
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050027 const char devPath[] = "\0mctp-mux";
28 int returnCode = 0;
29
30 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
31 if (-1 == sockFd)
32 {
33 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060034 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050035 return returnCode;
36 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060037 Logger(pldmVerbose, "Success in creating the socket : RC = ", sockFd);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050038
39 struct sockaddr_un addr
George Liu6492f522020-06-16 10:34:05 +080040 {};
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050041 addr.sun_family = AF_UNIX;
42
43 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
44
45 CustomFD socketFd(sockFd);
46 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
47 sizeof(devPath) + sizeof(addr.sun_family) - 1);
48 if (-1 == result)
49 {
50 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080051 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060052 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050053 return returnCode;
54 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060055 Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050056
57 auto pldmType = MCTP_MSG_TYPE_PLDM;
58 result = write(socketFd(), &pldmType, sizeof(pldmType));
59 if (-1 == result)
60 {
61 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080062 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060063 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050064 return returnCode;
65 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060066 Logger(
67 pldmVerbose,
68 "Success in sending message type as pldm to mctp : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050069
70 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
71 if (-1 == result)
72 {
73 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060074 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050075 return returnCode;
76 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060077 Logger(pldmVerbose, "Write to socket successful : RC = ", result);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050078
79 // Read the response from socket
80 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
81 if (0 == peekedLength)
82 {
John Wang58a0e062019-11-08 15:38:15 +080083 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -060084 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050085 return returnCode;
86 }
87 else if (peekedLength <= -1)
88 {
89 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060090 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050091 return returnCode;
92 }
93 else
94 {
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -060095 auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
96 do
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050097 {
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050098 ssize_t peekedLength =
99 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500100 responseMsg.resize(peekedLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600101 auto recvDataLength =
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500102 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
103 peekedLength, 0);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600104 auto resphdr =
105 reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
106 if (recvDataLength == peekedLength &&
107 resphdr->instance_id == reqhdr->instance_id &&
108 resphdr->request != PLDM_REQUEST)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500109 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600110 Logger(pldmVerbose, "Total length:", recvDataLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600111 break;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500112 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600113 else if (recvDataLength != peekedLength)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500114 {
John Wang58a0e062019-11-08 15:38:15 +0800115 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600116 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500117 return returnCode;
118 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600119 } while (1);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500120 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800121
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500122 returnCode = shutdown(socketFd(), SHUT_RDWR);
123 if (-1 == returnCode)
124 {
125 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800126 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600127 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500128 return returnCode;
129 }
130
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600131 Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500132 return PLDM_SUCCESS;
133}
John Wang58a0e062019-11-08 15:38:15 +0800134
135void CommandInterface::exec()
136{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600137 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
138 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
139 auto& bus = pldm::utils::DBusHandler::getBus();
140 try
141 {
142 auto service =
143 pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
144 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
145 pldmRequester, "GetInstanceId");
146 method.append(mctp_eid);
147 auto reply = bus.call(method);
148 reply.read(instanceId);
149 }
150 catch (const std::exception& e)
151 {
152 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = " << mctp_eid
153 << ", error = " << e.what() << "\n";
154 return;
155 }
John Wang58a0e062019-11-08 15:38:15 +0800156 auto [rc, requestMsg] = createRequestMsg();
157 if (rc != PLDM_SUCCESS)
158 {
159 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600160 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800161 return;
162 }
163
John Wangb754eee2020-02-15 16:10:25 +0800164 std::vector<uint8_t> responseMsg;
165 rc = pldmSendRecv(requestMsg, responseMsg);
166
167 if (rc != PLDM_SUCCESS)
168 {
169 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
170 return;
171 }
172
173 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
174 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
175}
176
177int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
178 std::vector<uint8_t>& responseMsg)
179{
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600180
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800181 // Insert the PLDM message type and EID at the beginning of the
182 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800183 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800184 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800185
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600186 bool mctpVerbose = pldmVerbose;
187
188 // By default enable request/response msgs for pldmtool raw commands.
189 if (CommandInterface::pldmType == "raw")
190 {
191 pldmVerbose = true;
192 }
193
194 Logger(pldmVerbose, "Request Message:", "");
195 printBuffer(requestMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800196
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800197 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800198 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800199 int fd = pldm_open();
200 if (-1 == fd)
201 {
202 std::cerr << "failed to init mctp "
203 << "\n";
204 return -1;
205 }
206 uint8_t* responseMessage = nullptr;
207 size_t responseMessageSize{};
Sampa Misra9f8d2b02021-03-24 08:33:14 +0000208 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
209 requestMsg.size() - 2, &responseMessage,
210 &responseMessageSize);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800211
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600212 Logger(pldmVerbose, "Response Message:", "");
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800213 responseMsg.resize(responseMessageSize);
214 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
215
216 free(responseMessage);
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600217 printBuffer(responseMsg, pldmVerbose);
John Wang58a0e062019-11-08 15:38:15 +0800218 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800219 else
220 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600221 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
222 Logger(pldmVerbose, "Response Message:", "");
223 printBuffer(responseMsg, pldmVerbose);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800224 responseMsg.erase(responseMsg.begin(),
225 responseMsg.begin() + 2 /* skip the mctp header */);
226 }
John Wangb754eee2020-02-15 16:10:25 +0800227 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800228}
John Wang58a0e062019-11-08 15:38:15 +0800229} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600230} // namespace pldmtool