blob: dce56258d1ec5ce2edc23a519ed18401f97fd48f [file] [log] [blame]
Jinu Joy Thomasf666db12019-05-29 05:22:31 -05001#include "libpldmresponder/base.hpp"
2#include "libpldmresponder/bios.hpp"
Sampa Misraa2fa0702019-05-31 01:28:55 -05003#include "libpldmresponder/platform.hpp"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -05004#include "libpldmresponder/utils.hpp"
5#include "registration.hpp"
6
7#include <err.h>
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +05308#include <getopt.h>
Jinu Joy Thomasf666db12019-05-29 05:22:31 -05009#include <poll.h>
10#include <stdlib.h>
11#include <sys/socket.h>
12#include <sys/types.h>
13#include <sys/un.h>
14#include <unistd.h>
15
16#include <cstdio>
17#include <cstring>
18#include <iomanip>
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +053019#include <iostream>
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050020#include <iterator>
21#include <phosphor-logging/log.hpp>
Deepak Kodihalli37998bf2019-11-11 04:06:53 -060022#include <sdeventplus/event.hpp>
23#include <sdeventplus/source/io.hpp>
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050024#include <sstream>
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +053025#include <string>
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050026#include <vector>
27
28#include "libpldm/base.h"
29#include "libpldm/bios.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050030#include "libpldm/platform.h"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050031
32#ifdef OEM_IBM
33#include "libpldmresponder/file_io.hpp"
34#endif
35
36constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
37
38using namespace phosphor::logging;
39using namespace pldm;
Deepak Kodihalli37998bf2019-11-11 04:06:53 -060040using namespace sdeventplus;
41using namespace sdeventplus::source;
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050042
43static Response processRxMsg(const std::vector<uint8_t>& requestMsg)
44{
45
46 Response response;
47 uint8_t eid = requestMsg[0];
48 uint8_t type = requestMsg[1];
49 pldm_header_info hdrFields{};
50 auto hdr = reinterpret_cast<const pldm_msg_hdr*>(
51 requestMsg.data() + sizeof(eid) + sizeof(type));
52 if (PLDM_SUCCESS != unpack_pldm_header(hdr, &hdrFields))
53 {
54 log<level::ERR>("Empty PLDM request header");
55 }
56 else if (PLDM_RESPONSE != hdrFields.msg_type)
57 {
58 auto request = reinterpret_cast<const pldm_msg*>(hdr);
59 size_t requestLen = requestMsg.size() - sizeof(struct pldm_msg_hdr) -
60 sizeof(eid) - sizeof(type);
61 response = pldm::responder::invokeHandler(
62 hdrFields.pldm_type, hdrFields.command, request, requestLen);
63 if (response.empty())
64 {
65 uint8_t completion_code = PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
66 response.resize(sizeof(pldm_msg_hdr));
67 auto responseHdr = reinterpret_cast<pldm_msg_hdr*>(response.data());
68 pldm_header_info header{};
69 header.msg_type = PLDM_RESPONSE;
70 header.instance = hdrFields.instance;
71 header.pldm_type = hdrFields.pldm_type;
72 header.command = hdrFields.command;
73 auto result = pack_pldm_header(&header, responseHdr);
74 if (PLDM_SUCCESS != result)
75 {
76 log<level::ERR>("Failed adding response header");
77 }
78 response.insert(response.end(), completion_code);
79 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050080 }
81 return response;
82}
83
84void printBuffer(const std::vector<uint8_t>& buffer)
85{
86 std::ostringstream tempStream;
87 tempStream << "Buffer Data: ";
88 if (!buffer.empty())
89 {
90 for (int byte : buffer)
91 {
92 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
93 << " ";
94 }
95 }
96 log<level::INFO>(tempStream.str().c_str());
97}
98
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +053099void optionUsage(void)
100{
101 std::cerr << "Usage: pldmd [options]\n";
102 std::cerr << "Options:\n";
103 std::cerr
104 << " --verbose=<0/1> 0 - Disable verbosity, 1 - Enable verbosity\n";
105 std::cerr << "Defaulted settings: --verbose=0 \n";
106}
107
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500108int main(int argc, char** argv)
109{
110
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530111 bool verbose = false;
112 static struct option long_options[] = {
113 {"verbose", required_argument, 0, 'v'}, {0, 0, 0, 0}};
114
115 auto argflag = getopt_long(argc, argv, "v:", long_options, nullptr);
116 switch (argflag)
117 {
118 case 'v':
119 switch (std::stoi(optarg))
120 {
121 case 0:
122 verbose = false;
123 break;
124 case 1:
125 verbose = true;
126 break;
127 default:
128 optionUsage();
129 break;
130 }
131 break;
132 default:
133 optionUsage();
134 break;
135 }
136
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500137 pldm::responder::base::registerHandlers();
138 pldm::responder::bios::registerHandlers();
Sampa Misraa2fa0702019-05-31 01:28:55 -0500139 pldm::responder::platform::registerHandlers();
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500140
141#ifdef OEM_IBM
142 pldm::responder::oem_ibm::registerHandlers();
143#endif
144
145 /* Create local socket. */
146 int returnCode = 0;
147 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
148 if (-1 == sockfd)
149 {
150 returnCode = -errno;
151 log<level::ERR>("Failed to create the socket",
152 entry("RC=%d", returnCode));
153 exit(EXIT_FAILURE);
154 }
155
156 responder::utils::CustomFD socketFd(sockfd);
157
158 struct sockaddr_un addr
159 {
160 };
161 addr.sun_family = AF_UNIX;
162 const char path[] = "\0mctp-mux";
163 memcpy(addr.sun_path, path, sizeof(path) - 1);
164 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
165 sizeof(path) + sizeof(addr.sun_family) - 1);
166 if (-1 == result)
167 {
168 returnCode = -errno;
169 log<level::ERR>("Failed to connect to the socket",
170 entry("RC=%d", returnCode));
171 exit(EXIT_FAILURE);
172 }
173
174 result = write(socketFd(), &MCTP_MSG_TYPE_PLDM, sizeof(MCTP_MSG_TYPE_PLDM));
175 if (-1 == result)
176 {
177 returnCode = -errno;
178 log<level::ERR>("Failed to send message type as pldm to mctp",
179 entry("RC=%d", returnCode));
180 exit(EXIT_FAILURE);
181 }
182
Deepak Kodihalli37998bf2019-11-11 04:06:53 -0600183 auto callback = [verbose](IO& /*io*/, int fd, uint32_t revents) {
184 if (!(revents & EPOLLIN))
185 {
186 return;
187 }
188
189 // Outgoing message.
190 struct iovec iov[2]{};
191
192 // This structure contains the parameter information for the response
193 // message.
194 struct msghdr msg
195 {
196 };
197
198 int returnCode = 0;
199 ssize_t peekedLength = recv(fd, nullptr, 0, MSG_PEEK | MSG_TRUNC);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500200 if (0 == peekedLength)
201 {
202 log<level::ERR>("Socket has been closed");
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500203 }
204 else if (peekedLength <= -1)
205 {
206 returnCode = -errno;
207 log<level::ERR>("recv system call failed",
208 entry("RC=%d", returnCode));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500209 }
210 else
211 {
212 std::vector<uint8_t> requestMsg(peekedLength);
213 auto recvDataLength = recv(
Deepak Kodihalli37998bf2019-11-11 04:06:53 -0600214 fd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500215 if (recvDataLength == peekedLength)
216 {
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530217 if (verbose)
218 {
219 log<level::INFO>("Received Msg ",
220 entry("LENGTH=%zu", recvDataLength),
221 entry("EID=0x%02x", requestMsg[0]),
222 entry("TYPE=0x%02x", requestMsg[1]));
223 printBuffer(requestMsg);
224 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500225 if (MCTP_MSG_TYPE_PLDM != requestMsg[1])
226 {
227 // Skip this message and continue.
228 log<level::ERR>("Encountered Non-PLDM type message",
229 entry("TYPE=0x%02x", requestMsg[1]));
230 }
231 else
232 {
233 // process message and send response
234 auto response = processRxMsg(requestMsg);
235 if (!response.empty())
236 {
Deepak Kodihalli8ffbbe02019-08-14 06:51:38 -0500237 if (verbose)
238 {
239 log<level::INFO>("Sending Msg ");
240 printBuffer(response);
241 }
242
Zahed Hossain09a96e02019-08-06 07:42:37 -0500243 iov[0].iov_base = &requestMsg[0];
244 iov[0].iov_len =
245 sizeof(requestMsg[0]) + sizeof(requestMsg[1]);
246 iov[1].iov_base = response.data();
247 iov[1].iov_len = response.size();
248
249 msg.msg_iov = iov;
250 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
251
Deepak Kodihalli37998bf2019-11-11 04:06:53 -0600252 int result = sendmsg(fd, &msg, 0);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500253 if (-1 == result)
254 {
255 returnCode = -errno;
256 log<level::ERR>("sendto system call failed",
257 entry("RC=%d", returnCode));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500258 }
259 }
260 }
261 }
262 else
263 {
264 log<level::ERR>("Failure to read peeked length packet",
265 entry("PEEKED_LENGTH=%zu", peekedLength),
266 entry("READ_LENGTH=%zu", recvDataLength));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500267 }
268 }
Deepak Kodihalli37998bf2019-11-11 04:06:53 -0600269 };
270
271 auto event = Event::get_default();
272 IO io(event, socketFd(), EPOLLIN, std::move(callback));
273 event.loop();
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500274
275 result = shutdown(sockfd, SHUT_RDWR);
276 if (-1 == result)
277 {
278 returnCode = -errno;
279 log<level::ERR>("Failed to shutdown the socket",
280 entry("RC=%d", returnCode));
281 exit(EXIT_FAILURE);
282 }
283 exit(EXIT_FAILURE);
284}