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