blob: 039e9840d8a1a10b12002b6b908dd5196f9a02d6 [file] [log] [blame]
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05001#include "pldm_cmd_helper.hpp"
2
Andrew Jeffery27a022c2022-08-10 23:12:49 +09303#include "libpldm/pldm.h"
George Liu6492f522020-06-16 10:34:05 +08004
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{
28 const char devPath[] = "\0mctp-mux";
29 int returnCode = 0;
30
31 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
32 if (-1 == sockFd)
33 {
34 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060035 std::cerr << "Failed to create the socket : RC = " << sockFd << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050036 return returnCode;
37 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060038 Logger(pldmVerbose, "Success in creating the socket : RC = ", sockFd);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050039
40 struct sockaddr_un addr
George Liu6492f522020-06-16 10:34:05 +080041 {};
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050042 addr.sun_family = AF_UNIX;
43
44 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
45
46 CustomFD socketFd(sockFd);
47 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
48 sizeof(devPath) + sizeof(addr.sun_family) - 1);
49 if (-1 == result)
50 {
51 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080052 std::cerr << "Failed to connect to socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -060053 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050054 return returnCode;
55 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060056 Logger(pldmVerbose, "Success in connecting to socket : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050057
58 auto pldmType = MCTP_MSG_TYPE_PLDM;
59 result = write(socketFd(), &pldmType, sizeof(pldmType));
60 if (-1 == result)
61 {
62 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080063 std::cerr << "Failed to send message type as pldm to mctp : RC = "
Sampa Misraaa8ae722019-12-12 03:20:40 -060064 << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050065 return returnCode;
66 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060067 Logger(
68 pldmVerbose,
69 "Success in sending message type as pldm to mctp : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050070
71 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
72 if (-1 == result)
73 {
74 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060075 std::cerr << "Write to socket failure : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050076 return returnCode;
77 }
Sridevi Rameshc91822b2020-02-27 09:26:41 -060078 Logger(pldmVerbose, "Write to socket successful : RC = ", result);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050079
80 // Read the response from socket
81 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
82 if (0 == peekedLength)
83 {
John Wang58a0e062019-11-08 15:38:15 +080084 std::cerr << "Socket is closed : peekedLength = " << peekedLength
Sampa Misraaa8ae722019-12-12 03:20:40 -060085 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050086 return returnCode;
87 }
88 else if (peekedLength <= -1)
89 {
90 returnCode = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -060091 std::cerr << "recv() system call failed : RC = " << returnCode << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050092 return returnCode;
93 }
94 else
95 {
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -060096 auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&requestMsg[2]);
97 do
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050098 {
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050099 ssize_t peekedLength =
100 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500101 responseMsg.resize(peekedLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600102 auto recvDataLength =
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500103 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
104 peekedLength, 0);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600105 auto resphdr =
106 reinterpret_cast<const pldm_msg_hdr*>(&responseMsg[2]);
107 if (recvDataLength == peekedLength &&
108 resphdr->instance_id == reqhdr->instance_id &&
109 resphdr->request != PLDM_REQUEST)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500110 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600111 Logger(pldmVerbose, "Total length:", recvDataLength);
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600112 break;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500113 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600114 else if (recvDataLength != peekedLength)
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500115 {
John Wang58a0e062019-11-08 15:38:15 +0800116 std::cerr << "Failure to read response length packet: length = "
Sampa Misraaa8ae722019-12-12 03:20:40 -0600117 << recvDataLength << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500118 return returnCode;
119 }
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600120 } while (1);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500121 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800122
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500123 returnCode = shutdown(socketFd(), SHUT_RDWR);
124 if (-1 == returnCode)
125 {
126 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800127 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
Sampa Misraaa8ae722019-12-12 03:20:40 -0600128 << "\n";
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500129 return returnCode;
130 }
131
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600132 Logger(pldmVerbose, "Shutdown Socket successful : RC = ", returnCode);
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500133 return PLDM_SUCCESS;
134}
John Wang58a0e062019-11-08 15:38:15 +0800135
136void CommandInterface::exec()
137{
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600138 static constexpr auto pldmObjPath = "/xyz/openbmc_project/pldm";
139 static constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
140 auto& bus = pldm::utils::DBusHandler::getBus();
141 try
142 {
143 auto service =
144 pldm::utils::DBusHandler().getService(pldmObjPath, pldmRequester);
145 auto method = bus.new_method_call(service.c_str(), pldmObjPath,
146 pldmRequester, "GetInstanceId");
147 method.append(mctp_eid);
148 auto reply = bus.call(method);
149 reply.read(instanceId);
150 }
151 catch (const std::exception& e)
152 {
Manojkiran Eda0a725f82021-10-23 06:02:26 +0530153 std::cerr << "GetInstanceId D-Bus call failed, MCTP id = "
154 << (unsigned)mctp_eid << ", error = " << e.what() << "\n";
Pavithra Barithayaac3c45a2020-03-05 02:28:26 -0600155 return;
156 }
John Wang58a0e062019-11-08 15:38:15 +0800157 auto [rc, requestMsg] = createRequestMsg();
158 if (rc != PLDM_SUCCESS)
159 {
160 std::cerr << "Failed to encode request message for " << pldmType << ":"
Sampa Misraaa8ae722019-12-12 03:20:40 -0600161 << commandName << " rc = " << rc << "\n";
John Wang58a0e062019-11-08 15:38:15 +0800162 return;
163 }
164
John Wangb754eee2020-02-15 16:10:25 +0800165 std::vector<uint8_t> responseMsg;
166 rc = pldmSendRecv(requestMsg, responseMsg);
167
168 if (rc != PLDM_SUCCESS)
169 {
170 std::cerr << "pldmSendRecv: Failed to receive RC = " << rc << "\n";
171 return;
172 }
173
174 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg.data());
175 parseResponseMsg(responsePtr, responseMsg.size() - sizeof(pldm_msg_hdr));
176}
177
178int CommandInterface::pldmSendRecv(std::vector<uint8_t>& requestMsg,
179 std::vector<uint8_t>& responseMsg)
180{
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
Tom Josephe5268cd2021-09-07 13:04:03 +0530194 if (pldmVerbose)
195 {
196 std::cout << "pldmtool: ";
197 printBuffer(Tx, requestMsg);
198 }
John Wang58a0e062019-11-08 15:38:15 +0800199
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800200 if (mctp_eid != PLDM_ENTITY_ID)
John Wang58a0e062019-11-08 15:38:15 +0800201 {
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800202 int fd = pldm_open();
203 if (-1 == fd)
204 {
205 std::cerr << "failed to init mctp "
206 << "\n";
207 return -1;
208 }
209 uint8_t* responseMessage = nullptr;
210 size_t responseMessageSize{};
Sampa Misra9f8d2b02021-03-24 08:33:14 +0000211 pldm_send_recv(mctp_eid, fd, requestMsg.data() + 2,
212 requestMsg.size() - 2, &responseMessage,
213 &responseMessageSize);
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800214
215 responseMsg.resize(responseMessageSize);
216 memcpy(responseMsg.data(), responseMessage, responseMsg.size());
217
218 free(responseMessage);
Tom Josephe5268cd2021-09-07 13:04:03 +0530219 if (pldmVerbose)
220 {
221 std::cout << "pldmtool: ";
222 printBuffer(Rx, responseMsg);
223 }
John Wang58a0e062019-11-08 15:38:15 +0800224 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800225 else
226 {
Sridevi Rameshc91822b2020-02-27 09:26:41 -0600227 mctpSockSendRecv(requestMsg, responseMsg, mctpVerbose);
Tom Josephe5268cd2021-09-07 13:04:03 +0530228 if (pldmVerbose)
229 {
230 std::cout << "pldmtool: ";
231 printBuffer(Rx, responseMsg);
232 }
Pavithra Barithayaf5ad6c72019-12-06 15:10:52 +0800233 responseMsg.erase(responseMsg.begin(),
234 responseMsg.begin() + 2 /* skip the mctp header */);
235 }
John Wangb754eee2020-02-15 16:10:25 +0800236 return PLDM_SUCCESS;
John Wang58a0e062019-11-08 15:38:15 +0800237}
John Wang58a0e062019-11-08 15:38:15 +0800238} // namespace helper
Sampa Misraaa8ae722019-12-12 03:20:40 -0600239} // namespace pldmtool