blob: 4fee0246dc25b436b58bd420d9fea14862ea56d2 [file] [log] [blame]
Tom Joseph0c6d22c2019-06-26 09:58:41 +05301#include "config.h"
2
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +05303#include "file_io.hpp"
4
George Liu6492f522020-06-16 10:34:05 +08005#include "libpldm/base.h"
6
Sampa Misra854e61f2019-08-22 04:36:47 -05007#include "file_io_by_type.hpp"
Tom Joseph0c6d22c2019-06-26 09:58:41 +05308#include "file_table.hpp"
Ravi Tejace1c96f2020-10-05 23:13:01 -05009#include "utils.hpp"
Sampa Misra854e61f2019-08-22 04:36:47 -050010#include "xyz/openbmc_project/Common/error.hpp"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050011
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053012#include <fcntl.h>
13#include <sys/mman.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <unistd.h>
17
18#include <cstring>
19#include <fstream>
Sampa Misraaa8ae722019-12-12 03:20:40 -060020#include <iostream>
Sampa Misra854e61f2019-08-22 04:36:47 -050021#include <memory>
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053022
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053023namespace pldm
24{
Ravi Tejace1c96f2020-10-05 23:13:01 -050025using namespace pldm::responder::utils;
Sampa Misra854e61f2019-08-22 04:36:47 -050026using namespace sdbusplus::xyz::openbmc_project::Common::Error;
27
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053028namespace responder
29{
30
31namespace fs = std::filesystem;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053032
33namespace dma
34{
35
36/** @struct AspeedXdmaOp
37 *
38 * Structure representing XDMA operation
39 */
40struct AspeedXdmaOp
41{
42 uint64_t hostAddr; //!< the DMA address on the host side, configured by
43 //!< PCI subsystem.
44 uint32_t len; //!< the size of the transfer in bytes, it should be a
45 //!< multiple of 16 bytes
46 uint32_t upstream; //!< boolean indicating the direction of the DMA
47 //!< operation, true means a transfer from BMC to host.
48};
49
Deepak Kodihalli134cc1b2019-10-04 01:51:02 -050050constexpr auto xdmaDev = "/dev/aspeed-xdma";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053051
Ravi Tejace1c96f2020-10-05 23:13:01 -050052int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address)
53{
54 static const size_t pageSize = getpagesize();
55 uint32_t numPages = length / pageSize;
56 uint32_t pageAlignedLength = numPages * pageSize;
57
58 if (length > pageAlignedLength)
59 {
60 pageAlignedLength += pageSize;
61 }
62
63 auto mmapCleanup = [pageAlignedLength](void* vgaMem) {
64 munmap(vgaMem, pageAlignedLength);
65 };
66
67 int dmaFd = -1;
68 int rc = 0;
69 dmaFd = open(xdmaDev, O_RDWR);
70 if (dmaFd < 0)
71 {
72 rc = -errno;
73 std::cerr << "Failed to open the XDMA device, RC=" << rc << "\n";
74 return rc;
75 }
76
77 pldm::utils::CustomFD xdmaFd(dmaFd);
78
79 void* vgaMem;
80 vgaMem =
81 mmap(nullptr, pageAlignedLength, PROT_READ, MAP_SHARED, xdmaFd(), 0);
82 if (MAP_FAILED == vgaMem)
83 {
84 rc = -errno;
85 std::cerr << "Failed to mmap the XDMA device, RC=" << rc << "\n";
86 return rc;
87 }
88
89 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
90
91 AspeedXdmaOp xdmaOp;
92 xdmaOp.upstream = 0;
93 xdmaOp.hostAddr = address;
94 xdmaOp.len = length;
95
96 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
97 if (rc < 0)
98 {
99 rc = -errno;
100 std::cerr << "Failed to execute the DMA operation, RC=" << rc
101 << " ADDRESS=" << address << " LENGTH=" << length << "\n";
102 return rc;
103 }
104
105 rc = writeToUnixSocket(fd, static_cast<const char*>(vgaMemPtr.get()),
106 length);
107 if (rc < 0)
108 {
109 rc = -errno;
110 close(fd);
111 std::cerr << "closing socket" << std::endl;
112 return rc;
113 }
114 return 0;
115}
116
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600117int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length,
118 uint64_t address, bool upstream)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530119{
120 static const size_t pageSize = getpagesize();
121 uint32_t numPages = length / pageSize;
122 uint32_t pageAlignedLength = numPages * pageSize;
123
124 if (length > pageAlignedLength)
125 {
126 pageAlignedLength += pageSize;
127 }
128
ArchanaKakani93409752022-04-19 00:36:04 -0500129 int rc = 0;
130 auto mmapCleanup = [pageAlignedLength, &rc](void* vgaMem) {
131 if (rc != -EINTR)
132 {
133 munmap(vgaMem, pageAlignedLength);
134 }
135 else
136 {
137 std::cerr
138 << "Received interrupt during DMA transfer. Skipping Unmap"
139 << std::endl;
140 }
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530141 };
142
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600143 int dmaFd = -1;
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600144 dmaFd = open(xdmaDev, O_RDWR);
145 if (dmaFd < 0)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530146 {
147 rc = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600148 std::cerr << "Failed to open the XDMA device, RC=" << rc << "\n";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530149 return rc;
150 }
151
George Liu83409572019-12-24 18:42:54 +0800152 pldm::utils::CustomFD xdmaFd(dmaFd);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530153
154 void* vgaMem;
155 vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ,
156 MAP_SHARED, xdmaFd(), 0);
157 if (MAP_FAILED == vgaMem)
158 {
159 rc = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600160 std::cerr << "Failed to mmap the XDMA device, RC=" << rc << "\n";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530161 return rc;
162 }
163
164 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
165
166 if (upstream)
167 {
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600168 rc = lseek(fd, offset, SEEK_SET);
169 if (rc == -1)
170 {
171 std::cerr << "lseek failed, ERROR=" << errno
172 << ", UPSTREAM=" << upstream << ", OFFSET=" << offset
173 << "\n";
174 return rc;
175 }
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530176
177 // Writing to the VGA memory should be aligned at page boundary,
178 // otherwise write data into a buffer aligned at page boundary and
179 // then write to the VGA memory.
180 std::vector<char> buffer{};
181 buffer.resize(pageAlignedLength);
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600182 rc = read(fd, buffer.data(), length);
183 if (rc == -1)
184 {
185 std::cerr << "file read failed, ERROR=" << errno
186 << ", UPSTREAM=" << upstream << ", LENGTH=" << length
187 << ", OFFSET=" << offset << "\n";
188 return rc;
189 }
190 if (rc != static_cast<int>(length))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530191 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600192 std::cerr << "mismatch between number of characters to read and "
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600193 << "the length read, LENGTH=" << length << " COUNT=" << rc
194 << "\n";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530195 return -1;
196 }
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600197 memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(),
198 pageAlignedLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530199 }
200
201 AspeedXdmaOp xdmaOp;
202 xdmaOp.upstream = upstream ? 1 : 0;
203 xdmaOp.hostAddr = address;
204 xdmaOp.len = length;
205
206 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
207 if (rc < 0)
208 {
209 rc = -errno;
Sampa Misraaa8ae722019-12-12 03:20:40 -0600210 std::cerr << "Failed to execute the DMA operation, RC=" << rc
211 << " UPSTREAM=" << upstream << " ADDRESS=" << address
212 << " LENGTH=" << length << "\n";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530213 return rc;
214 }
215
216 if (!upstream)
217 {
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600218 rc = lseek(fd, offset, SEEK_SET);
219 if (rc == -1)
Sampa Misra854e61f2019-08-22 04:36:47 -0500220 {
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600221 std::cerr << "lseek failed, ERROR=" << errno
222 << ", UPSTREAM=" << upstream << ", OFFSET=" << offset
223 << "\n";
224 return rc;
Sampa Misra854e61f2019-08-22 04:36:47 -0500225 }
Deepak Kodihalli15211b42019-12-14 02:24:49 -0600226 rc = write(fd, static_cast<const char*>(vgaMemPtr.get()), length);
227 if (rc == -1)
228 {
229 std::cerr << "file write failed, ERROR=" << errno
230 << ", UPSTREAM=" << upstream << ", LENGTH=" << length
231 << ", OFFSET=" << offset << "\n";
232 return rc;
233 }
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530234 }
235
236 return 0;
237}
238
239} // namespace dma
240
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600241namespace oem_ibm
242{
243
244Response Handler::readFileIntoMemory(const pldm_msg* request,
245 size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530246{
247 uint32_t fileHandle = 0;
248 uint32_t offset = 0;
249 uint32_t length = 0;
250 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530251
252 Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0);
253 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
254
255 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
256 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530257 encode_rw_file_memory_resp(request->hdr.instance_id,
258 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530259 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
260 return response;
261 }
262
Zahed Hossain223a73d2019-07-04 12:46:18 -0500263 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
264 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530265
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530266 using namespace pldm::filetable;
267 auto& table = buildFileTable(FILE_TABLE_JSON);
268 FileEntry value{};
269
270 try
271 {
272 value = table.at(fileHandle);
273 }
Patrick Williams51330582021-10-06 12:48:56 -0500274 catch (const std::exception& e)
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530275 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600276 std::cerr << "File handle does not exist in the file table, HANDLE="
277 << fileHandle << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530278 encode_rw_file_memory_resp(request->hdr.instance_id,
279 PLDM_READ_FILE_INTO_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530280 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
281 return response;
282 }
283
284 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530285 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600286 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530287 encode_rw_file_memory_resp(request->hdr.instance_id,
288 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530289 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
290 return response;
291 }
292
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530293 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530294 if (offset >= fileSize)
295 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600296 std::cerr << "Offset exceeds file size, OFFSET=" << offset
297 << " FILE_SIZE=" << fileSize << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530298 encode_rw_file_memory_resp(request->hdr.instance_id,
299 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530300 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
301 return response;
302 }
303
304 if (offset + length > fileSize)
305 {
306 length = fileSize - offset;
307 }
308
309 if (length % dma::minSize)
310 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600311 std::cerr << "Read length is not a multiple of DMA minSize, LENGTH="
312 << length << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530313 encode_rw_file_memory_resp(request->hdr.instance_id,
314 PLDM_READ_FILE_INTO_MEMORY,
Deepak Kodihalli3bf5c552020-04-20 06:16:01 -0500315 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530316 return response;
317 }
318
319 using namespace dma;
320 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530321 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530322 offset, length, address, true,
323 request->hdr.instance_id);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530324}
325
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600326Response Handler::writeFileFromMemory(const pldm_msg* request,
327 size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530328{
329 uint32_t fileHandle = 0;
330 uint32_t offset = 0;
331 uint32_t length = 0;
332 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530333
334 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
335 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
336
337 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
338 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530339 encode_rw_file_memory_resp(request->hdr.instance_id,
340 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530341 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
342 return response;
343 }
344
Zahed Hossain223a73d2019-07-04 12:46:18 -0500345 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
346 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530347
348 if (length % dma::minSize)
349 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600350 std::cerr << "Write length is not a multiple of DMA minSize, LENGTH="
351 << length << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530352 encode_rw_file_memory_resp(request->hdr.instance_id,
353 PLDM_WRITE_FILE_FROM_MEMORY,
Deepak Kodihalli3bf5c552020-04-20 06:16:01 -0500354 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530355 return response;
356 }
357
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530358 using namespace pldm::filetable;
359 auto& table = buildFileTable(FILE_TABLE_JSON);
360 FileEntry value{};
361
362 try
363 {
364 value = table.at(fileHandle);
365 }
Patrick Williams51330582021-10-06 12:48:56 -0500366 catch (const std::exception& e)
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530367 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600368 std::cerr << "File handle does not exist in the file table, HANDLE="
369 << fileHandle << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530370 encode_rw_file_memory_resp(request->hdr.instance_id,
371 PLDM_WRITE_FILE_FROM_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530372 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
373 return response;
374 }
375
376 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530377 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600378 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530379 encode_rw_file_memory_resp(request->hdr.instance_id,
380 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530381 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
382 return response;
383 }
384
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530385 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530386 if (offset >= fileSize)
387 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600388 std::cerr << "Offset exceeds file size, OFFSET=" << offset
389 << " FILE_SIZE=" << fileSize << "\n";
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530390 encode_rw_file_memory_resp(request->hdr.instance_id,
391 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530392 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
393 return response;
394 }
395
396 using namespace dma;
397 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530398 return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530399 offset, length, address, false,
400 request->hdr.instance_id);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530401}
402
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600403Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength)
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530404{
405 uint32_t transferHandle = 0;
406 uint8_t transferFlag = 0;
407 uint8_t tableType = 0;
408
409 Response response(sizeof(pldm_msg_hdr) +
410 PLDM_GET_FILE_TABLE_MIN_RESP_BYTES);
411 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
412
413 if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES)
414 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530415 encode_get_file_table_resp(request->hdr.instance_id,
416 PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0,
417 responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530418 return response;
419 }
420
Zahed Hossain223a73d2019-07-04 12:46:18 -0500421 auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle,
422 &transferFlag, &tableType);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530423 if (rc)
424 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530425 encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr,
426 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530427 return response;
428 }
429
430 if (tableType != PLDM_FILE_ATTRIBUTE_TABLE)
431 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530432 encode_get_file_table_resp(request->hdr.instance_id,
433 PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr,
434 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530435 return response;
436 }
437
438 using namespace pldm::filetable;
439 auto table = buildFileTable(FILE_TABLE_JSON);
440 auto attrTable = table();
441 response.resize(response.size() + attrTable.size());
442 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
443
444 if (attrTable.empty())
445 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530446 encode_get_file_table_resp(request->hdr.instance_id,
447 PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr,
448 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530449 return response;
450 }
451
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530452 encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
453 PLDM_START_AND_END, attrTable.data(),
454 attrTable.size(), responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530455 return response;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530456}
457
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600458Response Handler::readFile(const pldm_msg* request, size_t payloadLength)
vkaverap5b914c32019-06-30 22:23:54 -0500459{
460 uint32_t fileHandle = 0;
461 uint32_t offset = 0;
462 uint32_t length = 0;
463
464 Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES);
465 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
466
467 if (payloadLength != PLDM_READ_FILE_REQ_BYTES)
468 {
469 encode_read_file_resp(request->hdr.instance_id,
470 PLDM_ERROR_INVALID_LENGTH, length, responsePtr);
471 return response;
472 }
473
474 auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset,
475 &length);
476
477 if (rc)
478 {
479 encode_read_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
480 return response;
481 }
482
483 using namespace pldm::filetable;
484 auto& table = buildFileTable(FILE_TABLE_JSON);
485 FileEntry value{};
486
487 try
488 {
489 value = table.at(fileHandle);
490 }
Patrick Williams51330582021-10-06 12:48:56 -0500491 catch (const std::exception& e)
vkaverap5b914c32019-06-30 22:23:54 -0500492 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600493 std::cerr << "File handle does not exist in the file table, HANDLE="
494 << fileHandle << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500495 encode_read_file_resp(request->hdr.instance_id,
496 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
497 return response;
498 }
499
500 if (!fs::exists(value.fsPath))
501 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600502 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500503 encode_read_file_resp(request->hdr.instance_id,
504 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
505 return response;
506 }
507
508 auto fileSize = fs::file_size(value.fsPath);
509 if (offset >= fileSize)
510 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600511 std::cerr << "Offset exceeds file size, OFFSET=" << offset
512 << " FILE_SIZE=" << fileSize << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500513 encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
514 length, responsePtr);
515 return response;
516 }
517
518 if (offset + length > fileSize)
519 {
520 length = fileSize - offset;
521 }
522
523 response.resize(response.size() + length);
524 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
525 auto fileDataPos = reinterpret_cast<char*>(responsePtr);
526 fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length);
527
528 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
529 stream.seekg(offset);
530 stream.read(fileDataPos, length);
531
532 encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
533 responsePtr);
534
535 return response;
536}
537
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600538Response Handler::writeFile(const pldm_msg* request, size_t payloadLength)
vkaverap5b914c32019-06-30 22:23:54 -0500539{
540 uint32_t fileHandle = 0;
541 uint32_t offset = 0;
542 uint32_t length = 0;
543 size_t fileDataOffset = 0;
544
545 Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES);
546 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
547
548 if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES)
549 {
550 encode_write_file_resp(request->hdr.instance_id,
551 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
552 return response;
553 }
554
555 auto rc = decode_write_file_req(request, payloadLength, &fileHandle,
556 &offset, &length, &fileDataOffset);
557
558 if (rc)
559 {
560 encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
561 return response;
562 }
563
564 using namespace pldm::filetable;
565 auto& table = buildFileTable(FILE_TABLE_JSON);
566 FileEntry value{};
567
568 try
569 {
570 value = table.at(fileHandle);
571 }
Patrick Williams51330582021-10-06 12:48:56 -0500572 catch (const std::exception& e)
vkaverap5b914c32019-06-30 22:23:54 -0500573 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600574 std::cerr << "File handle does not exist in the file table, HANDLE="
575 << fileHandle << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500576 encode_write_file_resp(request->hdr.instance_id,
577 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
578 return response;
579 }
580
581 if (!fs::exists(value.fsPath))
582 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600583 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500584 encode_write_file_resp(request->hdr.instance_id,
585 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
586 return response;
587 }
588
589 auto fileSize = fs::file_size(value.fsPath);
590 if (offset >= fileSize)
591 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600592 std::cerr << "Offset exceeds file size, OFFSET=" << offset
593 << " FILE_SIZE=" << fileSize << "\n";
vkaverap5b914c32019-06-30 22:23:54 -0500594 encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
595 0, responsePtr);
596 return response;
597 }
598
599 auto fileDataPos =
600 reinterpret_cast<const char*>(request->payload) + fileDataOffset;
601
602 std::ofstream stream(value.fsPath,
603 std::ios::in | std::ios::out | std::ios::binary);
604 stream.seekp(offset);
605 stream.write(fileDataPos, length);
606
607 encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
608 responsePtr);
609
610 return response;
611}
612
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600613Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
Sampa Misra69508502020-09-08 00:08:21 -0500614 size_t payloadLength,
615 oem_platform::Handler* oemPlatformHandler)
Sampa Misra854e61f2019-08-22 04:36:47 -0500616{
617 Response response(
618 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
619 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
620
621 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES)
622 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600623 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
624 PLDM_ERROR_INVALID_LENGTH, 0,
625 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500626 return response;
627 }
628
629 uint16_t fileType{};
630 uint32_t fileHandle{};
631 uint32_t offset{};
632 uint32_t length{};
633 uint64_t address{};
634 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength,
635 &fileType, &fileHandle, &offset,
636 &length, &address);
637 if (rc != PLDM_SUCCESS)
638 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600639 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
640 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500641 return response;
642 }
643 if (length % dma::minSize)
644 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600645 std::cerr << "Length is not a multiple of DMA minSize, LENGTH="
646 << length << "\n";
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600647 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
Deepak Kodihalli3bf5c552020-04-20 06:16:01 -0500648 PLDM_ERROR_INVALID_LENGTH, 0,
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600649 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500650 return response;
651 }
652
653 std::unique_ptr<FileHandler> handler{};
654 try
655 {
656 handler = getHandlerByType(fileType, fileHandle);
657 }
658 catch (const InternalFailure& e)
659 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600660 std::cerr << "unknown file type, TYPE=" << fileType << "\n";
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600661 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
662 PLDM_INVALID_FILE_TYPE, 0,
663 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500664 return response;
665 }
666
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600667 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
Sampa Misra69508502020-09-08 00:08:21 -0500668 ? handler->writeFromMemory(offset, length, address,
669 oemPlatformHandler)
670 : handler->readIntoMemory(offset, length, address,
671 oemPlatformHandler);
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600672 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
Sampa Misra854e61f2019-08-22 04:36:47 -0500673 length, responsePtr);
674 return response;
675}
676
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600677Response Handler::writeFileByTypeFromMemory(const pldm_msg* request,
678 size_t payloadLength)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600679{
680 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
Sampa Misra69508502020-09-08 00:08:21 -0500681 payloadLength, oemPlatformHandler);
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600682}
683
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600684Response Handler::readFileByTypeIntoMemory(const pldm_msg* request,
685 size_t payloadLength)
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600686{
687 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
Sampa Misra69508502020-09-08 00:08:21 -0500688 payloadLength, oemPlatformHandler);
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600689}
690
Sampa Misra18967162020-01-14 02:31:41 -0600691Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength)
692{
693 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
694 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
695
Sampa Misrad823cc02020-03-24 04:53:20 -0500696 if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
Sampa Misra18967162020-01-14 02:31:41 -0600697 {
698 encode_rw_file_by_type_resp(request->hdr.instance_id,
699 PLDM_WRITE_FILE_BY_TYPE,
700 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
701 return response;
702 }
703 uint16_t fileType{};
704 uint32_t fileHandle{};
705 uint32_t offset{};
706 uint32_t length{};
707
708 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
709 &fileHandle, &offset, &length);
710 if (rc != PLDM_SUCCESS)
711 {
712 encode_rw_file_by_type_resp(request->hdr.instance_id,
713 PLDM_WRITE_FILE_BY_TYPE, rc, 0,
714 responsePtr);
715 return response;
716 }
717
718 std::unique_ptr<FileHandler> handler{};
719 try
720 {
721 handler = getHandlerByType(fileType, fileHandle);
722 }
723 catch (const InternalFailure& e)
724 {
725 std::cerr << "unknown file type, TYPE=" << fileType << "\n";
726 encode_rw_file_by_type_resp(request->hdr.instance_id,
727 PLDM_WRITE_FILE_BY_TYPE,
728 PLDM_INVALID_FILE_TYPE, 0, responsePtr);
729 return response;
730 }
731
732 rc = handler->write(reinterpret_cast<const char*>(
Sampa Misrad823cc02020-03-24 04:53:20 -0500733 request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES),
Sampa Misra69508502020-09-08 00:08:21 -0500734 offset, length, oemPlatformHandler);
Sampa Misra18967162020-01-14 02:31:41 -0600735 encode_rw_file_by_type_resp(request->hdr.instance_id,
736 PLDM_WRITE_FILE_BY_TYPE, rc, length,
737 responsePtr);
738 return response;
739}
740
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600741Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength)
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600742{
743 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
744 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
745
746 if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
747 {
748 encode_rw_file_by_type_resp(request->hdr.instance_id,
749 PLDM_READ_FILE_BY_TYPE,
750 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
751 return response;
752 }
753 uint16_t fileType{};
754 uint32_t fileHandle{};
755 uint32_t offset{};
756 uint32_t length{};
757
758 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
759 &fileHandle, &offset, &length);
760 if (rc != PLDM_SUCCESS)
761 {
762 encode_rw_file_by_type_resp(request->hdr.instance_id,
763 PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr);
764 return response;
765 }
766
767 std::unique_ptr<FileHandler> handler{};
768 try
769 {
770 handler = getHandlerByType(fileType, fileHandle);
771 }
772 catch (const InternalFailure& e)
773 {
Sampa Misraaa8ae722019-12-12 03:20:40 -0600774 std::cerr << "unknown file type, TYPE=" << fileType << "\n";
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600775 encode_rw_file_by_type_resp(request->hdr.instance_id,
776 PLDM_READ_FILE_BY_TYPE,
777 PLDM_INVALID_FILE_TYPE, 0, responsePtr);
778 return response;
779 }
780
Sampa Misra69508502020-09-08 00:08:21 -0500781 rc = handler->read(offset, length, response, oemPlatformHandler);
Deepak Kodihalli9a26f892019-12-10 06:48:06 -0600782 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600783 encode_rw_file_by_type_resp(request->hdr.instance_id,
784 PLDM_READ_FILE_BY_TYPE, rc, length,
785 responsePtr);
786 return response;
787}
788
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600789Response Handler::fileAck(const pldm_msg* request, size_t payloadLength)
790{
791 Response response(sizeof(pldm_msg_hdr) + PLDM_FILE_ACK_RESP_BYTES);
792 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
793
794 if (payloadLength != PLDM_FILE_ACK_REQ_BYTES)
795 {
796 encode_file_ack_resp(request->hdr.instance_id,
797 PLDM_ERROR_INVALID_LENGTH, responsePtr);
798 return response;
799 }
800 uint16_t fileType{};
801 uint32_t fileHandle{};
802 uint8_t fileStatus{};
803
804 auto rc = decode_file_ack_req(request, payloadLength, &fileType,
805 &fileHandle, &fileStatus);
806 if (rc != PLDM_SUCCESS)
807 {
808 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr);
809 return response;
810 }
811
812 std::unique_ptr<FileHandler> handler{};
813 try
814 {
815 handler = getHandlerByType(fileType, fileHandle);
816 }
Sampa Misra18967162020-01-14 02:31:41 -0600817
Deepak Kodihalli2da1bfe2019-12-14 08:28:09 -0600818 catch (const InternalFailure& e)
819 {
820 encode_file_ack_resp(request->hdr.instance_id, PLDM_INVALID_FILE_TYPE,
821 responsePtr);
822 return response;
823 }
824
825 rc = handler->fileAck(fileStatus);
826 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr);
827 return response;
828}
829
George Liu89aad712020-03-12 13:34:51 +0800830Response Handler::getAlertStatus(const pldm_msg* request, size_t payloadLength)
831{
832 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_ALERT_STATUS_RESP_BYTES);
833 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
834 if (payloadLength != PLDM_GET_ALERT_STATUS_REQ_BYTES)
835 {
836 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
837 }
838
839 uint8_t versionId{};
840
841 auto rc = decode_get_alert_status_req(request, payloadLength, &versionId);
842 if (rc != PLDM_SUCCESS)
843 {
844 return CmdHandler::ccOnlyResponse(request, rc);
845 }
846
847 if (versionId != 0)
848 {
849 return CmdHandler::ccOnlyResponse(request,
850 PLDM_HOST_UNSUPPORTED_FORMAT_VERSION);
851 }
852
853 constexpr uint32_t rackEntry = 0xFF000030;
854 constexpr uint32_t priCecNode = 0x00008030;
855 rc = encode_get_alert_status_resp(request->hdr.instance_id, PLDM_SUCCESS,
856 rackEntry, priCecNode, responsePtr,
857 PLDM_GET_ALERT_STATUS_RESP_BYTES);
858 if (rc != PLDM_SUCCESS)
859 {
860 return CmdHandler::ccOnlyResponse(request, rc);
861 }
862
863 return response;
864}
865
Sampa Misra18967162020-01-14 02:31:41 -0600866Response Handler::newFileAvailable(const pldm_msg* request,
867 size_t payloadLength)
868{
869 Response response(sizeof(pldm_msg_hdr) + PLDM_NEW_FILE_RESP_BYTES);
870
871 if (payloadLength != PLDM_NEW_FILE_REQ_BYTES)
872 {
873 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
874 }
875 uint16_t fileType{};
876 uint32_t fileHandle{};
877 uint64_t length{};
878
879 auto rc = decode_new_file_req(request, payloadLength, &fileType,
880 &fileHandle, &length);
881
882 if (rc != PLDM_SUCCESS)
883 {
884 return CmdHandler::ccOnlyResponse(request, rc);
885 }
886
887 std::unique_ptr<FileHandler> handler{};
888 try
889 {
890 handler = getHandlerByType(fileType, fileHandle);
891 }
892 catch (const InternalFailure& e)
893 {
894 std::cerr << "unknown file type, TYPE=" << fileType << "\n";
895 return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE);
896 }
897
898 rc = handler->newFileAvailable(length);
899 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
900 encode_new_file_resp(request->hdr.instance_id, rc, responsePtr);
901 return response;
902}
903
Deepak Kodihallibc669f12019-11-28 08:52:07 -0600904} // namespace oem_ibm
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530905} // namespace responder
906} // namespace pldm