blob: 5623975bd1e0934b68db3f4d329cb297055bb49c [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>
22#include <sstream>
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +053023#include <string>
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050024#include <vector>
25
26#include "libpldm/base.h"
27#include "libpldm/bios.h"
Sampa Misraa2fa0702019-05-31 01:28:55 -050028#include "libpldm/platform.h"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050029
30#ifdef OEM_IBM
31#include "libpldmresponder/file_io.hpp"
32#endif
33
34constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
35
36using namespace phosphor::logging;
37using namespace pldm;
38
39static Response processRxMsg(const std::vector<uint8_t>& requestMsg)
40{
41
42 Response response;
43 uint8_t eid = requestMsg[0];
44 uint8_t type = requestMsg[1];
45 pldm_header_info hdrFields{};
46 auto hdr = reinterpret_cast<const pldm_msg_hdr*>(
47 requestMsg.data() + sizeof(eid) + sizeof(type));
48 if (PLDM_SUCCESS != unpack_pldm_header(hdr, &hdrFields))
49 {
50 log<level::ERR>("Empty PLDM request header");
51 }
52 else if (PLDM_RESPONSE != hdrFields.msg_type)
53 {
54 auto request = reinterpret_cast<const pldm_msg*>(hdr);
55 size_t requestLen = requestMsg.size() - sizeof(struct pldm_msg_hdr) -
56 sizeof(eid) - sizeof(type);
57 response = pldm::responder::invokeHandler(
58 hdrFields.pldm_type, hdrFields.command, request, requestLen);
59 if (response.empty())
60 {
61 uint8_t completion_code = PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
62 response.resize(sizeof(pldm_msg_hdr));
63 auto responseHdr = reinterpret_cast<pldm_msg_hdr*>(response.data());
64 pldm_header_info header{};
65 header.msg_type = PLDM_RESPONSE;
66 header.instance = hdrFields.instance;
67 header.pldm_type = hdrFields.pldm_type;
68 header.command = hdrFields.command;
69 auto result = pack_pldm_header(&header, responseHdr);
70 if (PLDM_SUCCESS != result)
71 {
72 log<level::ERR>("Failed adding response header");
73 }
74 response.insert(response.end(), completion_code);
75 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050076 }
77 return response;
78}
79
80void printBuffer(const std::vector<uint8_t>& buffer)
81{
82 std::ostringstream tempStream;
83 tempStream << "Buffer Data: ";
84 if (!buffer.empty())
85 {
86 for (int byte : buffer)
87 {
88 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
89 << " ";
90 }
91 }
92 log<level::INFO>(tempStream.str().c_str());
93}
94
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +053095void optionUsage(void)
96{
97 std::cerr << "Usage: pldmd [options]\n";
98 std::cerr << "Options:\n";
99 std::cerr
100 << " --verbose=<0/1> 0 - Disable verbosity, 1 - Enable verbosity\n";
101 std::cerr << "Defaulted settings: --verbose=0 \n";
102}
103
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500104int main(int argc, char** argv)
105{
106
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530107 bool verbose = false;
108 static struct option long_options[] = {
109 {"verbose", required_argument, 0, 'v'}, {0, 0, 0, 0}};
110
111 auto argflag = getopt_long(argc, argv, "v:", long_options, nullptr);
112 switch (argflag)
113 {
114 case 'v':
115 switch (std::stoi(optarg))
116 {
117 case 0:
118 verbose = false;
119 break;
120 case 1:
121 verbose = true;
122 break;
123 default:
124 optionUsage();
125 break;
126 }
127 break;
128 default:
129 optionUsage();
130 break;
131 }
132
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500133 pldm::responder::base::registerHandlers();
134 pldm::responder::bios::registerHandlers();
Sampa Misraa2fa0702019-05-31 01:28:55 -0500135 pldm::responder::platform::registerHandlers();
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500136
Zahed Hossain09a96e02019-08-06 07:42:37 -0500137 // Outgoing message.
138 struct iovec iov[2]{};
139
140 // This structure contains the parameter information for the response
141 // message.
142 struct msghdr msg
143 {
144 };
145
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500146#ifdef OEM_IBM
147 pldm::responder::oem_ibm::registerHandlers();
148#endif
149
150 /* Create local socket. */
151 int returnCode = 0;
152 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
153 if (-1 == sockfd)
154 {
155 returnCode = -errno;
156 log<level::ERR>("Failed to create the socket",
157 entry("RC=%d", returnCode));
158 exit(EXIT_FAILURE);
159 }
160
161 responder::utils::CustomFD socketFd(sockfd);
162
163 struct sockaddr_un addr
164 {
165 };
166 addr.sun_family = AF_UNIX;
167 const char path[] = "\0mctp-mux";
168 memcpy(addr.sun_path, path, sizeof(path) - 1);
169 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
170 sizeof(path) + sizeof(addr.sun_family) - 1);
171 if (-1 == result)
172 {
173 returnCode = -errno;
174 log<level::ERR>("Failed to connect to the socket",
175 entry("RC=%d", returnCode));
176 exit(EXIT_FAILURE);
177 }
178
179 result = write(socketFd(), &MCTP_MSG_TYPE_PLDM, sizeof(MCTP_MSG_TYPE_PLDM));
180 if (-1 == result)
181 {
182 returnCode = -errno;
183 log<level::ERR>("Failed to send message type as pldm to mctp",
184 entry("RC=%d", returnCode));
185 exit(EXIT_FAILURE);
186 }
187
188 do
189 {
190 ssize_t peekedLength =
191 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
192 if (0 == peekedLength)
193 {
194 log<level::ERR>("Socket has been closed");
195 exit(EXIT_FAILURE);
196 }
197 else if (peekedLength <= -1)
198 {
199 returnCode = -errno;
200 log<level::ERR>("recv system call failed",
201 entry("RC=%d", returnCode));
202 exit(EXIT_FAILURE);
203 }
204 else
205 {
206 std::vector<uint8_t> requestMsg(peekedLength);
207 auto recvDataLength = recv(
208 sockfd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
209 if (recvDataLength == peekedLength)
210 {
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530211 if (verbose)
212 {
213 log<level::INFO>("Received Msg ",
214 entry("LENGTH=%zu", recvDataLength),
215 entry("EID=0x%02x", requestMsg[0]),
216 entry("TYPE=0x%02x", requestMsg[1]));
217 printBuffer(requestMsg);
218 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500219 if (MCTP_MSG_TYPE_PLDM != requestMsg[1])
220 {
221 // Skip this message and continue.
222 log<level::ERR>("Encountered Non-PLDM type message",
223 entry("TYPE=0x%02x", requestMsg[1]));
224 }
225 else
226 {
227 // process message and send response
228 auto response = processRxMsg(requestMsg);
229 if (!response.empty())
230 {
Deepak Kodihalli8ffbbe02019-08-14 06:51:38 -0500231 if (verbose)
232 {
233 log<level::INFO>("Sending Msg ");
234 printBuffer(response);
235 }
236
Zahed Hossain09a96e02019-08-06 07:42:37 -0500237 iov[0].iov_base = &requestMsg[0];
238 iov[0].iov_len =
239 sizeof(requestMsg[0]) + sizeof(requestMsg[1]);
240 iov[1].iov_base = response.data();
241 iov[1].iov_len = response.size();
242
243 msg.msg_iov = iov;
244 msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
245
246 result = sendmsg(socketFd(), &msg, 0);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500247 if (-1 == result)
248 {
249 returnCode = -errno;
250 log<level::ERR>("sendto system call failed",
251 entry("RC=%d", returnCode));
252 exit(EXIT_FAILURE);
253 }
254 }
255 }
256 }
257 else
258 {
259 log<level::ERR>("Failure to read peeked length packet",
260 entry("PEEKED_LENGTH=%zu", peekedLength),
261 entry("READ_LENGTH=%zu", recvDataLength));
262 exit(EXIT_FAILURE);
263 }
264 }
265 } while (true);
266
267 result = shutdown(sockfd, SHUT_RDWR);
268 if (-1 == result)
269 {
270 returnCode = -errno;
271 log<level::ERR>("Failed to shutdown the socket",
272 entry("RC=%d", returnCode));
273 exit(EXIT_FAILURE);
274 }
275 exit(EXIT_FAILURE);
276}