blob: 05051b6ba2e63a16628b992018683ba9b7efe1d1 [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));
Deepak Kodihalli75e02f82019-11-20 02:51:05 -060050 registerHandler(PLDM_OEM, PLDM_READ_FILE_BY_TYPE,
51 std::move(readFileByType));
Jinu Joy Thomasf666db12019-05-29 05:22:31 -050052}
53
54} // namespace oem_ibm
55
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053056namespace fs = std::filesystem;
57using namespace phosphor::logging;
58
59namespace dma
60{
61
62/** @struct AspeedXdmaOp
63 *
64 * Structure representing XDMA operation
65 */
66struct AspeedXdmaOp
67{
68 uint64_t hostAddr; //!< the DMA address on the host side, configured by
69 //!< PCI subsystem.
70 uint32_t len; //!< the size of the transfer in bytes, it should be a
71 //!< multiple of 16 bytes
72 uint32_t upstream; //!< boolean indicating the direction of the DMA
73 //!< operation, true means a transfer from BMC to host.
74};
75
Deepak Kodihalli134cc1b2019-10-04 01:51:02 -050076constexpr auto xdmaDev = "/dev/aspeed-xdma";
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +053077
78int DMA::transferDataHost(const fs::path& path, uint32_t offset,
79 uint32_t length, uint64_t address, bool upstream)
80{
81 static const size_t pageSize = getpagesize();
82 uint32_t numPages = length / pageSize;
83 uint32_t pageAlignedLength = numPages * pageSize;
84
85 if (length > pageAlignedLength)
86 {
87 pageAlignedLength += pageSize;
88 }
89
90 auto mmapCleanup = [pageAlignedLength](void* vgaMem) {
91 munmap(vgaMem, pageAlignedLength);
92 };
93
94 int fd = -1;
95 int rc = 0;
96 fd = open(xdmaDev, O_RDWR);
97 if (fd < 0)
98 {
99 rc = -errno;
100 log<level::ERR>("Failed to open the XDMA device", entry("RC=%d", rc));
101 return rc;
102 }
103
104 utils::CustomFD xdmaFd(fd);
105
106 void* vgaMem;
107 vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ,
108 MAP_SHARED, xdmaFd(), 0);
109 if (MAP_FAILED == vgaMem)
110 {
111 rc = -errno;
112 log<level::ERR>("Failed to mmap the XDMA device", entry("RC=%d", rc));
113 return rc;
114 }
115
116 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
117
118 if (upstream)
119 {
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530120 std::ifstream stream(path.string(), std::ios::in | std::ios::binary);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530121 stream.seekg(offset);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530122
123 // Writing to the VGA memory should be aligned at page boundary,
124 // otherwise write data into a buffer aligned at page boundary and
125 // then write to the VGA memory.
126 std::vector<char> buffer{};
127 buffer.resize(pageAlignedLength);
128 stream.read(buffer.data(), length);
129 memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(),
130 pageAlignedLength);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530131
132 if (static_cast<uint32_t>(stream.gcount()) != length)
133 {
134 log<level::ERR>("mismatch between number of characters to read and "
135 "the length read",
136 entry("LENGTH=%d", length),
137 entry("COUNT=%d", stream.gcount()));
138 return -1;
139 }
140 }
141
142 AspeedXdmaOp xdmaOp;
143 xdmaOp.upstream = upstream ? 1 : 0;
144 xdmaOp.hostAddr = address;
145 xdmaOp.len = length;
146
147 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
148 if (rc < 0)
149 {
150 rc = -errno;
151 log<level::ERR>("Failed to execute the DMA operation",
152 entry("RC=%d", rc), entry("UPSTREAM=%d", upstream),
153 entry("ADDRESS=%lld", address),
154 entry("LENGTH=%d", length));
155 return rc;
156 }
157
158 if (!upstream)
159 {
Sampa Misra854e61f2019-08-22 04:36:47 -0500160 std::ios_base::openmode mode = std::ios::out | std::ios::binary;
161 if (fs::exists(path))
162 {
163 mode |= std::ios::in;
164 }
165 std::ofstream stream(path.string(), mode);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530166
167 stream.seekp(offset);
168 stream.write(static_cast<const char*>(vgaMemPtr.get()), length);
169 }
170
171 return 0;
172}
173
174} // namespace dma
175
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500176Response readFileIntoMemory(const pldm_msg* request, size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530177{
178 uint32_t fileHandle = 0;
179 uint32_t offset = 0;
180 uint32_t length = 0;
181 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530182
183 Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0);
184 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
185
186 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
187 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530188 encode_rw_file_memory_resp(request->hdr.instance_id,
189 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530190 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
191 return response;
192 }
193
Zahed Hossain223a73d2019-07-04 12:46:18 -0500194 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
195 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530196
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530197 using namespace pldm::filetable;
198 auto& table = buildFileTable(FILE_TABLE_JSON);
199 FileEntry value{};
200
201 try
202 {
203 value = table.at(fileHandle);
204 }
205 catch (std::exception& e)
206 {
207 log<level::ERR>("File handle does not exist in the file table",
208 entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530209 encode_rw_file_memory_resp(request->hdr.instance_id,
210 PLDM_READ_FILE_INTO_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530211 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
212 return response;
213 }
214
215 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530216 {
217 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530218 encode_rw_file_memory_resp(request->hdr.instance_id,
219 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530220 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
221 return response;
222 }
223
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530224 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530225 if (offset >= fileSize)
226 {
227 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
228 entry("FILE_SIZE=%d", fileSize));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530229 encode_rw_file_memory_resp(request->hdr.instance_id,
230 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530231 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
232 return response;
233 }
234
235 if (offset + length > fileSize)
236 {
237 length = fileSize - offset;
238 }
239
240 if (length % dma::minSize)
241 {
242 log<level::ERR>("Read length is not a multiple of DMA minSize",
243 entry("LENGTH=%d", length));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530244 encode_rw_file_memory_resp(request->hdr.instance_id,
245 PLDM_READ_FILE_INTO_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530246 PLDM_INVALID_READ_LENGTH, 0, responsePtr);
247 return response;
248 }
249
250 using namespace dma;
251 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530252 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530253 offset, length, address, true,
254 request->hdr.instance_id);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530255}
256
Jinu Joy Thomasf666db12019-05-29 05:22:31 -0500257Response writeFileFromMemory(const pldm_msg* request, size_t payloadLength)
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530258{
259 uint32_t fileHandle = 0;
260 uint32_t offset = 0;
261 uint32_t length = 0;
262 uint64_t address = 0;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530263
264 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
265 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
266
267 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
268 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530269 encode_rw_file_memory_resp(request->hdr.instance_id,
270 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530271 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
272 return response;
273 }
274
Zahed Hossain223a73d2019-07-04 12:46:18 -0500275 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
276 &length, &address);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530277
278 if (length % dma::minSize)
279 {
280 log<level::ERR>("Write length is not a multiple of DMA minSize",
281 entry("LENGTH=%d", length));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530282 encode_rw_file_memory_resp(request->hdr.instance_id,
283 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530284 PLDM_INVALID_WRITE_LENGTH, 0, responsePtr);
285 return response;
286 }
287
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530288 using namespace pldm::filetable;
289 auto& table = buildFileTable(FILE_TABLE_JSON);
290 FileEntry value{};
291
292 try
293 {
294 value = table.at(fileHandle);
295 }
296 catch (std::exception& e)
297 {
298 log<level::ERR>("File handle does not exist in the file table",
299 entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530300 encode_rw_file_memory_resp(request->hdr.instance_id,
301 PLDM_WRITE_FILE_FROM_MEMORY,
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530302 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
303 return response;
304 }
305
306 if (!fs::exists(value.fsPath))
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530307 {
308 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530309 encode_rw_file_memory_resp(request->hdr.instance_id,
310 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530311 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
312 return response;
313 }
314
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530315 auto fileSize = fs::file_size(value.fsPath);
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530316 if (offset >= fileSize)
317 {
318 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
319 entry("FILE_SIZE=%d", fileSize));
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530320 encode_rw_file_memory_resp(request->hdr.instance_id,
321 PLDM_WRITE_FILE_FROM_MEMORY,
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530322 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
323 return response;
324 }
325
326 using namespace dma;
327 DMA intf;
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530328 return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath,
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530329 offset, length, address, false,
330 request->hdr.instance_id);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530331}
332
333Response getFileTable(const pldm_msg* request, size_t payloadLength)
334{
335 uint32_t transferHandle = 0;
336 uint8_t transferFlag = 0;
337 uint8_t tableType = 0;
338
339 Response response(sizeof(pldm_msg_hdr) +
340 PLDM_GET_FILE_TABLE_MIN_RESP_BYTES);
341 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
342
343 if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES)
344 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530345 encode_get_file_table_resp(request->hdr.instance_id,
346 PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0,
347 responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530348 return response;
349 }
350
Zahed Hossain223a73d2019-07-04 12:46:18 -0500351 auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle,
352 &transferFlag, &tableType);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530353 if (rc)
354 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530355 encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr,
356 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530357 return response;
358 }
359
360 if (tableType != PLDM_FILE_ATTRIBUTE_TABLE)
361 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530362 encode_get_file_table_resp(request->hdr.instance_id,
363 PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr,
364 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530365 return response;
366 }
367
368 using namespace pldm::filetable;
369 auto table = buildFileTable(FILE_TABLE_JSON);
370 auto attrTable = table();
371 response.resize(response.size() + attrTable.size());
372 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
373
374 if (attrTable.empty())
375 {
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530376 encode_get_file_table_resp(request->hdr.instance_id,
377 PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr,
378 0, responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530379 return response;
380 }
381
Jinu Joy Thomas33705fd2019-07-02 16:03:05 +0530382 encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
383 PLDM_START_AND_END, attrTable.data(),
384 attrTable.size(), responsePtr);
Tom Joseph0c6d22c2019-06-26 09:58:41 +0530385 return response;
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530386}
387
vkaverap5b914c32019-06-30 22:23:54 -0500388Response readFile(const pldm_msg* request, size_t payloadLength)
389{
390 uint32_t fileHandle = 0;
391 uint32_t offset = 0;
392 uint32_t length = 0;
393
394 Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES);
395 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
396
397 if (payloadLength != PLDM_READ_FILE_REQ_BYTES)
398 {
399 encode_read_file_resp(request->hdr.instance_id,
400 PLDM_ERROR_INVALID_LENGTH, length, responsePtr);
401 return response;
402 }
403
404 auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset,
405 &length);
406
407 if (rc)
408 {
409 encode_read_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
410 return response;
411 }
412
413 using namespace pldm::filetable;
414 auto& table = buildFileTable(FILE_TABLE_JSON);
415 FileEntry value{};
416
417 try
418 {
419 value = table.at(fileHandle);
420 }
421 catch (std::exception& e)
422 {
423 log<level::ERR>("File handle does not exist in the file table",
424 entry("HANDLE=%d", fileHandle));
425 encode_read_file_resp(request->hdr.instance_id,
426 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
427 return response;
428 }
429
430 if (!fs::exists(value.fsPath))
431 {
432 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
433 encode_read_file_resp(request->hdr.instance_id,
434 PLDM_INVALID_FILE_HANDLE, length, responsePtr);
435 return response;
436 }
437
438 auto fileSize = fs::file_size(value.fsPath);
439 if (offset >= fileSize)
440 {
441 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
442 entry("FILE_SIZE=%d", fileSize));
443 encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
444 length, responsePtr);
445 return response;
446 }
447
448 if (offset + length > fileSize)
449 {
450 length = fileSize - offset;
451 }
452
453 response.resize(response.size() + length);
454 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
455 auto fileDataPos = reinterpret_cast<char*>(responsePtr);
456 fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length);
457
458 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
459 stream.seekg(offset);
460 stream.read(fileDataPos, length);
461
462 encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
463 responsePtr);
464
465 return response;
466}
467
468Response writeFile(const pldm_msg* request, size_t payloadLength)
469{
470 uint32_t fileHandle = 0;
471 uint32_t offset = 0;
472 uint32_t length = 0;
473 size_t fileDataOffset = 0;
474
475 Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES);
476 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
477
478 if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES)
479 {
480 encode_write_file_resp(request->hdr.instance_id,
481 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
482 return response;
483 }
484
485 auto rc = decode_write_file_req(request, payloadLength, &fileHandle,
486 &offset, &length, &fileDataOffset);
487
488 if (rc)
489 {
490 encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
491 return response;
492 }
493
494 using namespace pldm::filetable;
495 auto& table = buildFileTable(FILE_TABLE_JSON);
496 FileEntry value{};
497
498 try
499 {
500 value = table.at(fileHandle);
501 }
502 catch (std::exception& e)
503 {
504 log<level::ERR>("File handle does not exist in the file table",
505 entry("HANDLE=%d", fileHandle));
506 encode_write_file_resp(request->hdr.instance_id,
507 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
508 return response;
509 }
510
511 if (!fs::exists(value.fsPath))
512 {
513 log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle));
514 encode_write_file_resp(request->hdr.instance_id,
515 PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
516 return response;
517 }
518
519 auto fileSize = fs::file_size(value.fsPath);
520 if (offset >= fileSize)
521 {
522 log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
523 entry("FILE_SIZE=%d", fileSize));
524 encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
525 0, responsePtr);
526 return response;
527 }
528
529 auto fileDataPos =
530 reinterpret_cast<const char*>(request->payload) + fileDataOffset;
531
532 std::ofstream stream(value.fsPath,
533 std::ios::in | std::ios::out | std::ios::binary);
534 stream.seekp(offset);
535 stream.write(fileDataPos, length);
536
537 encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
538 responsePtr);
539
540 return response;
541}
542
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600543Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
544 size_t payloadLength)
Sampa Misra854e61f2019-08-22 04:36:47 -0500545{
546 Response response(
547 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
548 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
549
550 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES)
551 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600552 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
553 PLDM_ERROR_INVALID_LENGTH, 0,
554 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500555 return response;
556 }
557
558 uint16_t fileType{};
559 uint32_t fileHandle{};
560 uint32_t offset{};
561 uint32_t length{};
562 uint64_t address{};
563 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength,
564 &fileType, &fileHandle, &offset,
565 &length, &address);
566 if (rc != PLDM_SUCCESS)
567 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600568 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
569 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500570 return response;
571 }
572 if (length % dma::minSize)
573 {
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600574 log<level::ERR>("Length is not a multiple of DMA minSize",
Sampa Misra854e61f2019-08-22 04:36:47 -0500575 entry("LENGTH=%d", length));
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600576 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
577 PLDM_INVALID_WRITE_LENGTH, 0,
578 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500579 return response;
580 }
581
582 std::unique_ptr<FileHandler> handler{};
583 try
584 {
585 handler = getHandlerByType(fileType, fileHandle);
586 }
587 catch (const InternalFailure& e)
588 {
589 log<level::ERR>("unknown file type ", entry("TYPE=%d", fileType));
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600590 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
591 PLDM_INVALID_FILE_TYPE, 0,
592 responsePtr);
Sampa Misra854e61f2019-08-22 04:36:47 -0500593 return response;
594 }
595
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600596 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
597 ? handler->writeFromMemory(offset, length, address)
598 : handler->readIntoMemory(offset, length, address);
599 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
Sampa Misra854e61f2019-08-22 04:36:47 -0500600 length, responsePtr);
601 return response;
602}
603
Deepak Kodihallif6d3a832019-11-19 07:00:29 -0600604Response writeFileByTypeFromMemory(const pldm_msg* request,
605 size_t payloadLength)
606{
607 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
608 payloadLength);
609}
610
611Response readFileByTypeIntoMemory(const pldm_msg* request, size_t payloadLength)
612{
613 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
614 payloadLength);
615}
616
Deepak Kodihalli75e02f82019-11-20 02:51:05 -0600617Response readFileByType(const pldm_msg* request, size_t payloadLength)
618{
619 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
620 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
621
622 if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
623 {
624 encode_rw_file_by_type_resp(request->hdr.instance_id,
625 PLDM_READ_FILE_BY_TYPE,
626 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
627 return response;
628 }
629 uint16_t fileType{};
630 uint32_t fileHandle{};
631 uint32_t offset{};
632 uint32_t length{};
633
634 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
635 &fileHandle, &offset, &length);
636 if (rc != PLDM_SUCCESS)
637 {
638 encode_rw_file_by_type_resp(request->hdr.instance_id,
639 PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr);
640 return response;
641 }
642
643 std::unique_ptr<FileHandler> handler{};
644 try
645 {
646 handler = getHandlerByType(fileType, fileHandle);
647 }
648 catch (const InternalFailure& e)
649 {
650 log<level::ERR>("unknown file type", entry("TYPE=%d", fileType));
651 encode_rw_file_by_type_resp(request->hdr.instance_id,
652 PLDM_READ_FILE_BY_TYPE,
653 PLDM_INVALID_FILE_TYPE, 0, responsePtr);
654 return response;
655 }
656
657 rc = handler->read(offset, length, response);
658 encode_rw_file_by_type_resp(request->hdr.instance_id,
659 PLDM_READ_FILE_BY_TYPE, rc, length,
660 responsePtr);
661 return response;
662}
663
Jinu Joy Thomas7f57f442019-06-13 20:38:49 +0530664} // namespace responder
665} // namespace pldm