blob: 3bf4295ce2295eb503f41510b49492bea77587e9 [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{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050017
John Wang58a0e062019-11-08 15:38:15 +080018namespace helper
19{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050020/*
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050021 * Initialize the socket, send pldm command & recieve response from socket
22 *
23 */
24int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
Sridevi Rameshc91822b2020-02-27 09:26:41 -060025 std::vector<uint8_t>& responseMsg, bool pldmVerbose)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050026{
27 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 {
Patrick Williams6da4f912023-05-10 07:50:53 -050098 ssize_t peekedLength = recv(socketFd(), nullptr, 0,
99 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 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500142 auto service = pldm::utils::DBusHandler().getService(pldmObjPath,
143 pldmRequester);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600144 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 {
Manojkiran Eda0a725f82021-10-23 06:02:26 +0530152 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = "
153 << (unsigned)mctp_eid << ", error = " << e.what() << "\n";
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600154 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{
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800180 // Insert the PLDM message type and EID at the beginning of the
181 // msg.
John Wang58a0e062019-11-08 15:38:15 +0800182 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800183 requestMsg.insert(requestMsg.begin(), mctp_eid);
John Wang58a0e062019-11-08 15:38:15 +0800184
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600185 bool mctpVerbose = pldmVerbose;
186
187 // By default enable request/response msgs for pldmtool raw commands.
188 if (CommandInterface::pldmType == "raw")
189 {
190 pldmVerbose = true;
191 }
192
Tom Josephe5268cd2021-09-07 13:04:03 +0530193 if (pldmVerbose)
194 {
195 std::cout << "pldmtool: ";
196 printBuffer(Tx, requestMsg);
197 }
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
214 responseMsg.resize(responseMessageSize);
215 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
216
Dung Cao2b85d782022-05-24 09:28:48 +0000217 shutdown(fd, SHUT_RDWR);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800218 free(responseMessage);
Dung Cao2b85d782022-05-24 09:28:48 +0000219
Tom Josephe5268cd2021-09-07 13:04:03 +0530220 if (pldmVerbose)
221 {
222 std::cout << "pldmtool: ";
223 printBuffer(Rx, responseMsg);
224 }
John Wang58a0e062019-11-08 15:38:15 +0800225 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800226 else
227 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600228 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
Tom Josephe5268cd2021-09-07 13:04:03 +0530229 if (pldmVerbose)
230 {
231 std::cout << "pldmtool: ";
232 printBuffer(Rx, responseMsg);
233 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800234 responseMsg.erase(responseMsg.begin(),
235 responseMsg.begin() + 2 /* skip the mctp header */);
236 }
John Wangb754eee2020-02-15 16:10:25 +0800237 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800238}
John Wang58a0e062019-11-08 15:38:15 +0800239} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600240} // namespace pldmtool