blob: 70723126c89334f05a858f6f1b167518a38fc193 [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 }
Deepak Kodihalli58c7a892019-08-01 04:57:57 -050074 response.insert(response.begin(), type);
75 response.insert(response.begin(), eid);
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();
135
136#ifdef OEM_IBM
137 pldm::responder::oem_ibm::registerHandlers();
138#endif
139
140 /* Create local socket. */
141 int returnCode = 0;
142 int sockfd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
143 if (-1 == sockfd)
144 {
145 returnCode = -errno;
146 log<level::ERR>("Failed to create the socket",
147 entry("RC=%d", returnCode));
148 exit(EXIT_FAILURE);
149 }
150
151 responder::utils::CustomFD socketFd(sockfd);
152
153 struct sockaddr_un addr
154 {
155 };
156 addr.sun_family = AF_UNIX;
157 const char path[] = "\0mctp-mux";
158 memcpy(addr.sun_path, path, sizeof(path) - 1);
159 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
160 sizeof(path) + sizeof(addr.sun_family) - 1);
161 if (-1 == result)
162 {
163 returnCode = -errno;
164 log<level::ERR>("Failed to connect to the socket",
165 entry("RC=%d", returnCode));
166 exit(EXIT_FAILURE);
167 }
168
169 result = write(socketFd(), &MCTP_MSG_TYPE_PLDM, sizeof(MCTP_MSG_TYPE_PLDM));
170 if (-1 == result)
171 {
172 returnCode = -errno;
173 log<level::ERR>("Failed to send message type as pldm to mctp",
174 entry("RC=%d", returnCode));
175 exit(EXIT_FAILURE);
176 }
177
178 do
179 {
180 ssize_t peekedLength =
181 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
182 if (0 == peekedLength)
183 {
184 log<level::ERR>("Socket has been closed");
185 exit(EXIT_FAILURE);
186 }
187 else if (peekedLength <= -1)
188 {
189 returnCode = -errno;
190 log<level::ERR>("recv system call failed",
191 entry("RC=%d", returnCode));
192 exit(EXIT_FAILURE);
193 }
194 else
195 {
196 std::vector<uint8_t> requestMsg(peekedLength);
197 auto recvDataLength = recv(
198 sockfd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
199 if (recvDataLength == peekedLength)
200 {
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530201 if (verbose)
202 {
203 log<level::INFO>("Received Msg ",
204 entry("LENGTH=%zu", recvDataLength),
205 entry("EID=0x%02x", requestMsg[0]),
206 entry("TYPE=0x%02x", requestMsg[1]));
207 printBuffer(requestMsg);
208 }
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500209 if (MCTP_MSG_TYPE_PLDM != requestMsg[1])
210 {
211 // Skip this message and continue.
212 log<level::ERR>("Encountered Non-PLDM type message",
213 entry("TYPE=0x%02x", requestMsg[1]));
214 }
215 else
216 {
217 // process message and send response
218 auto response = processRxMsg(requestMsg);
219 if (!response.empty())
220 {
Jinu Joy Thomas75dd4422019-07-22 12:47:12 +0530221 if (verbose)
222 {
223 log<level::INFO>("Sending Msg ");
224 printBuffer(response);
225 }
Deepak Kodihalli58c7a892019-08-01 04:57:57 -0500226 result = sendto(socketFd(), response.data(),
227 response.size(), 0, nullptr, 0);
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500228 if (-1 == result)
229 {
230 returnCode = -errno;
231 log<level::ERR>("sendto system call failed",
232 entry("RC=%d", returnCode));
233 exit(EXIT_FAILURE);
234 }
235 }
236 }
237 }
238 else
239 {
240 log<level::ERR>("Failure to read peeked length packet",
241 entry("PEEKED_LENGTH=%zu", peekedLength),
242 entry("READ_LENGTH=%zu", recvDataLength));
243 exit(EXIT_FAILURE);
244 }
245 }
246 } while (true);
247
248 result = shutdown(sockfd, SHUT_RDWR);
249 if (-1 == result)
250 {
251 returnCode = -errno;
252 log<level::ERR>("Failed to shutdown the socket",
253 entry("RC=%d", returnCode));
254 exit(EXIT_FAILURE);
255 }
256 exit(EXIT_FAILURE);
257}