blob: 0c7216ba2e7adf88f393fb242f68cadd4a695973 [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
Sampa Misra854e61f2019-08-22 04:36:47 -05005#include "file_io_by_type.hpp"
Tom Joseph0c6d22c2019-06-26 09:58:41 +05306#include "file_table.hpp"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -05007#include "libpldmresponder/utils.hpp"
8#include "registration.hpp"
Sampa Misra854e61f2019-08-22 04:36:47 -05009#include "xyz/openbmc_project/Common/error.hpp"
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050010
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053011#include <fcntl.h>
12#include <sys/mman.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
17#include <cstring>
18#include <fstream>
Sampa Misra854e61f2019-08-22 04:36:47 -050019#include <memory>
20#include <phosphor-logging/elog-errors.hpp>
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053021#include <phosphor-logging/log.hpp>
22
23#include "libpldm/base.h"
24
25namespace pldm
26{
27
Sampa Misra854e61f2019-08-22 04:36:47 -050028using namespace phosphor::logging;
29using namespace sdbusplus::xyz::openbmc_project::Common::Error;
30
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053031namespace responder
32{
33
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050034namespace oem_ibm
35{
36
37void registerHandlers()
38{
Tom Joseph0c6d22c2019-06-26 09:58:41 +053039 registerHandler(PLDM_OEM, PLDM_GET_FILE_TABLE, std::move(getFileTable));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050040 registerHandler(PLDM_OEM, PLDM_READ_FILE_INTO_MEMORY,
41 std::move(readFileIntoMemory));
42 registerHandler(PLDM_OEM, PLDM_WRITE_FILE_FROM_MEMORY,
43 std::move(writeFileFromMemory));
vkaverap5b914c32019-06-30 22:23:54 -050044 registerHandler(PLDM_OEM, PLDM_READ_FILE, std::move(readFile));
45 registerHandler(PLDM_OEM, PLDM_WRITE_FILE, std::move(writeFile));
Sampa Misra854e61f2019-08-22 04:36:47 -050046 registerHandler(PLDM_OEM, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
47 std::move(writeFileByTypeFromMemory));
Deepak Kodihallif6d3a832019-11-19 07:00:29 -060048 registerHandler(PLDM_OEM, PLDM_READ_FILE_BY_TYPE_INTO_MEMORY,
49 std::move(readFileByTypeIntoMemory));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050050}
51
52} // namespace oem_ibm
53
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053054namespace fs = std::filesystem;
55using namespace phosphor::logging;
56
57namespace dma
58{
59
60/** @struct AspeedXdmaOp
61 *
62 * Structure representing XDMA operation
63 */
64struct AspeedXdmaOp
65{
66 uint64_t hostAddr; //!< the DMA address on the host side, configured by
67 //!< PCI subsystem.
68 uint32_t len; //!< the size of the transfer in bytes, it should be a
69 //!< multiple of 16 bytes
70 uint32_t upstream; //!< boolean indicating the direction of the DMA
71 //!< operation, true means a transfer from BMC to host.
72};
73
Deepak Kodihalli134cc1b2019-10-04 01:51:02 -050074constexpr auto xdmaDev = "/dev/aspeed-xdma";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053075
76int DMA::transferDataHost(const fs::path& path, uint32_t offset,
77 uint32_t length, uint64_t address, bool upstream)
78{
79 static const size_t pageSize = getpagesize();
80 uint32_t numPages = length / pageSize;
81 uint32_t pageAlignedLength = numPages * pageSize;
82
83 if (length > pageAlignedLength)
84 {
85 pageAlignedLength += pageSize;
86 }
87
88 auto mmapCleanup = [pageAlignedLength](void* vgaMem) {
89 munmap(vgaMem, pageAlignedLength);
90 };
91
92 int fd = -1;
93 int rc = 0;
94 fd = open(xdmaDev, O_RDWR);
95 if (fd < 0)
96 {
97 rc = -errno;
98 log<level::ERR>("Failed to open the XDMA device", entry("RC=%d", rc));
99 return rc;
100 }
101
102 utils::CustomFD xdmaFd(fd);
103
104 void* vgaMem;
105 vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ,
106 MAP_SHARED, xdmaFd(), 0);
107 if (MAP_FAILED == vgaMem)
108 {
109 rc = -errno;
110 log<level::ERR>("Failed to mmap the XDMA device", entry("RC=%d", rc));
111 return rc;
112 }
113
114 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
115
116 if (upstream)
117 {
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530118 std::ifstream stream(path.string(), std::ios::in | std::ios::binary);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530119 stream.seekg(offset);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530120
121 // Writing to the VGA memory should be aligned at page boundary,
122 // otherwise write data into a buffer aligned at page boundary and
123 // then write to the VGA memory.
124 std::vector<char> buffer{};
125 buffer.resize(pageAlignedLength);
126 stream.read(buffer.data(), length);
127 memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(),
128 pageAlignedLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530129
130 if (static_cast<uint32_t>(stream.gcount()) != length)
131 {
132 log<level::ERR>("mismatch between number of characters to read and "
133 "the length read",
134 entry("LENGTH=%d", length),
135 entry("COUNT=%d", stream.gcount()));
136 return -1;
137 }
138 }
139
140 AspeedXdmaOp xdmaOp;
141 xdmaOp.upstream = upstream ? 1 : 0;
142 xdmaOp.hostAddr = address;
143 xdmaOp.len = length;
144
145 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
146 if (rc < 0)
147 {
148 rc = -errno;
149 log<level::ERR>("Failed to execute the DMA operation",
150 entry("RC=%d", rc), entry("UPSTREAM=%d", upstream),
151 entry("ADDRESS=%lld", address),
152 entry("LENGTH=%d", length));
153 return rc;
154 }
155
156 if (!upstream)
157 {
Sampa Misra854e61f2019-08-22 04:36:47 -0500158 std::ios_base::openmode mode = std::ios::out | std::ios::binary;
159 if (fs::exists(path))
160 {
161 mode |= std::ios::in;
162 }
163 std::ofstream stream(path.string(), mode);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530164
165 stream.seekp(offset);
166 stream.write(static_cast<const char*>(vgaMemPtr.get()), length);
167 }
168
169 return 0;
170}
171
172} // namespace dma
173
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500174Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530175{
176 uint32_t fileHandle = 0;
177 uint32_t offset = 0;
178 uint32_t length = 0;
179 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530180
181 Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0);
182 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
183
184 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
185 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530186 encode_rw_file_memory_resp(request->hdr.instance_id,
187 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530188 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
189 return response;
190 }
191
Zahed Hossain223a73d2019-07-04 12:46:18 -0500192 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
193 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530194
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530195 using namespace pldm::filetable;
196 auto& table = buildFileTable(FILE_TABLE_JSON);
197 FileEntry value{};
198
199 try
200 {
201 value = table.at(fileHandle);
202 }
203 catch (std::exception& e)
204 {
205 log<level::ERR>("File handle does not exist in the file table",
206 entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530207 encode_rw_file_memory_resp(request->hdr.instance_id,
208 PLDM_READ_FILE_INTO_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530209 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
210 return response;
211 }
212
213 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530214 {
215 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530216 encode_rw_file_memory_resp(request->hdr.instance_id,
217 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530218 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
219 return response;
220 }
221
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530222 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530223 if (offset >= fileSize)
224 {
225 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
226 entry("FILE_SIZE=%d", fileSize));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530227 encode_rw_file_memory_resp(request->hdr.instance_id,
228 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530229 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
230 return response;
231 }
232
233 if (offset + length > fileSize)
234 {
235 length = fileSize - offset;
236 }
237
238 if (length % dma::minSize)
239 {
240 log<level::ERR>("Read length is not a multiple of DMA minSize",
241 entry("LENGTH=%d", length));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530242 encode_rw_file_memory_resp(request->hdr.instance_id,
243 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530244 PLDM_INVALID_READ_LENGTH, 0, responsePtr);
245 return response;
246 }
247
248 using namespace dma;
249 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530250 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530251 offset, length, address, true,
252 request->hdr.instance_id);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530253}
254
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500255Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530256{
257 uint32_t fileHandle = 0;
258 uint32_t offset = 0;
259 uint32_t length = 0;
260 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530261
262 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
263 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
264
265 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
266 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530267 encode_rw_file_memory_resp(request->hdr.instance_id,
268 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530269 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
270 return response;
271 }
272
Zahed Hossain223a73d2019-07-04 12:46:18 -0500273 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
274 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530275
276 if (length % dma::minSize)
277 {
278 log<level::ERR>("Write length is not a multiple of DMA minSize",
279 entry("LENGTH=%d", length));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530280 encode_rw_file_memory_resp(request->hdr.instance_id,
281 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530282 PLDM_INVALID_WRITE_LENGTH, 0, responsePtr);
283 return response;
284 }
285
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530286 using namespace pldm::filetable;
287 auto& table = buildFileTable(FILE_TABLE_JSON);
288 FileEntry value{};
289
290 try
291 {
292 value = table.at(fileHandle);
293 }
294 catch (std::exception& e)
295 {
296 log<level::ERR>("File handle does not exist in the file table",
297 entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530298 encode_rw_file_memory_resp(request->hdr.instance_id,
299 PLDM_WRITE_FILE_FROM_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530300 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
301 return response;
302 }
303
304 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530305 {
306 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530307 encode_rw_file_memory_resp(request->hdr.instance_id,
308 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530309 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
310 return response;
311 }
312
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530313 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530314 if (offset >= fileSize)
315 {
316 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
317 entry("FILE_SIZE=%d", fileSize));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530318 encode_rw_file_memory_resp(request->hdr.instance_id,
319 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530320 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
321 return response;
322 }
323
324 using namespace dma;
325 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530326 return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530327 offset, length, address, false,
328 request->hdr.instance_id);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530329}
330
331Response getFileTable(const pldm_msg* request, size_t payloadLength)
332{
333 uint32_t transferHandle = 0;
334 uint8_t transferFlag = 0;
335 uint8_t tableType = 0;
336
337 Response response(sizeof(pldm_msg_hdr) +
338 PLDM_GET_FILE_TABLE_MIN_RESP_BYTES);
339 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
340
341 if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES)
342 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530343 encode_get_file_table_resp(request->hdr.instance_id,
344 PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0,
345 responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530346 return response;
347 }
348
Zahed Hossain223a73d2019-07-04 12:46:18 -0500349 auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle,
350 &transferFlag, &tableType);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530351 if (rc)
352 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530353 encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr,
354 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530355 return response;
356 }
357
358 if (tableType != PLDM_FILE_ATTRIBUTE_TABLE)
359 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530360 encode_get_file_table_resp(request->hdr.instance_id,
361 PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr,
362 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530363 return response;
364 }
365
366 using namespace pldm::filetable;
367 auto table = buildFileTable(FILE_TABLE_JSON);
368 auto attrTable = table();
369 response.resize(response.size() + attrTable.size());
370 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
371
372 if (attrTable.empty())
373 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530374 encode_get_file_table_resp(request->hdr.instance_id,
375 PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr,
376 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530377 return response;
378 }
379
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530380 encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
381 PLDM_START_AND_END, attrTable.data(),
382 attrTable.size(), responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530383 return response;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530384}
385
vkaverap5b914c32019-06-30 22:23:54 -0500386Response readFile(const pldm_msg* request, size_t payloadLength)
387{
388 uint32_t fileHandle = 0;
389 uint32_t offset = 0;
390 uint32_t length = 0;
391
392 Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES);
393 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
394
395 if (payloadLength != PLDM_READ_FILE_REQ_BYTES)
396 {
397 encode_read_file_resp(request->hdr.instance_id,
398 PLDM_ERROR_INVALID_LENGTH, length, responsePtr);
399 return response;
400 }
401
402 auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset,
403 &length);
404
405 if (rc)
406 {
407 encode_read_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
408 return response;
409 }
410
411 using namespace pldm::filetable;
412 auto& table = buildFileTable(FILE_TABLE_JSON);
413 FileEntry value{};
414
415 try
416 {
417 value = table.at(fileHandle);
418 }
419 catch (std::exception& e)
420 {
421 log<level::ERR>("File handle does not exist in the file table",
422 entry("HANDLE=%d", fileHandle));
423 encode_read_file_resp(request->hdr.instance_id,
424 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
425 return response;
426 }
427
428 if (!fs::exists(value.fsPath))
429 {
430 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
431 encode_read_file_resp(request->hdr.instance_id,
432 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
433 return response;
434 }
435
436 auto fileSize = fs::file_size(value.fsPath);
437 if (offset >= fileSize)
438 {
439 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
440 entry("FILE_SIZE=%d", fileSize));
441 encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
442 length, responsePtr);
443 return response;
444 }
445
446 if (offset + length > fileSize)
447 {
448 length = fileSize - offset;
449 }
450
451 response.resize(response.size() + length);
452 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
453 auto fileDataPos = reinterpret_cast<char*>(responsePtr);
454 fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length);
455
456 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
457 stream.seekg(offset);
458 stream.read(fileDataPos, length);
459
460 encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
461 responsePtr);
462
463 return response;
464}
465
466Response writeFile(const pldm_msg* request, size_t payloadLength)
467{
468 uint32_t fileHandle = 0;
469 uint32_t offset = 0;
470 uint32_t length = 0;
471 size_t fileDataOffset = 0;
472
473 Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES);
474 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
475
476 if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES)
477 {
478 encode_write_file_resp(request->hdr.instance_id,
479 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
480 return response;
481 }
482
483 auto rc = decode_write_file_req(request, payloadLength, &fileHandle,
484 &offset, &length, &fileDataOffset);
485
486 if (rc)
487 {
488 encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
489 return response;
490 }
491
492 using namespace pldm::filetable;
493 auto& table = buildFileTable(FILE_TABLE_JSON);
494 FileEntry value{};
495
496 try
497 {
498 value = table.at(fileHandle);
499 }
500 catch (std::exception& e)
501 {
502 log<level::ERR>("File handle does not exist in the file table",
503 entry("HANDLE=%d", fileHandle));
504 encode_write_file_resp(request->hdr.instance_id,
505 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
506 return response;
507 }
508
509 if (!fs::exists(value.fsPath))
510 {
511 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
512 encode_write_file_resp(request->hdr.instance_id,
513 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
514 return response;
515 }
516
517 auto fileSize = fs::file_size(value.fsPath);
518 if (offset >= fileSize)
519 {
520 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
521 entry("FILE_SIZE=%d", fileSize));
522 encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
523 0, responsePtr);
524 return response;
525 }
526
527 auto fileDataPos =
528 reinterpret_cast<const char*>(request->payload) + fileDataOffset;
529
530 std::ofstream stream(value.fsPath,
531 std::ios::in | std::ios::out | std::ios::binary);
532 stream.seekp(offset);
533 stream.write(fileDataPos, length);
534
535 encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
536 responsePtr);
537
538 return response;
539}
540
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600541Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
542 size_t payloadLength)
Sampa Misra854e61f2019-08-22 04:36:47 -0500543{
544 Response response(
545 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
546 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
547
548 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES)
549 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600550 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
551 PLDM_ERROR_INVALID_LENGTH, 0,
552 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500553 return response;
554 }
555
556 uint16_t fileType{};
557 uint32_t fileHandle{};
558 uint32_t offset{};
559 uint32_t length{};
560 uint64_t address{};
561 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength,
562 &fileType, &fileHandle, &offset,
563 &length, &address);
564 if (rc != PLDM_SUCCESS)
565 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600566 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
567 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500568 return response;
569 }
570 if (length % dma::minSize)
571 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600572 log<level::ERR>("Length is not a multiple of DMA minSize",
Sampa Misra854e61f2019-08-22 04:36:47 -0500573 entry("LENGTH=%d", length));
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600574 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
575 PLDM_INVALID_WRITE_LENGTH, 0,
576 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500577 return response;
578 }
579
580 std::unique_ptr<FileHandler> handler{};
581 try
582 {
583 handler = getHandlerByType(fileType, fileHandle);
584 }
585 catch (const InternalFailure& e)
586 {
587 log<level::ERR>("unknown file type ", entry("TYPE=%d", fileType));
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600588 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
589 PLDM_INVALID_FILE_TYPE, 0,
590 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500591 return response;
592 }
593
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600594 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
595 ? handler->writeFromMemory(offset, length, address)
596 : handler->readIntoMemory(offset, length, address);
597 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
Sampa Misra854e61f2019-08-22 04:36:47 -0500598 length, responsePtr);
599 return response;
600}
601
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600602Response writeFileByTypeFromMemory(const pldm_msg* request,
603 size_t payloadLength)
604{
605 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
606 payloadLength);
607}
608
609Response readFileByTypeIntoMemory(const pldm_msg* request, size_t payloadLength)
610{
611 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
612 payloadLength);
613}
614
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530615} // namespace responder
616} // namespace pldm