1 #include "config.h"
2 
3 #include "file_io.hpp"
4 
5 #include "file_io_by_type.hpp"
6 #include "file_table.hpp"
7 #include "utils.hpp"
8 #include "xyz/openbmc_project/Common/error.hpp"
9 
10 #include <fcntl.h>
11 #include <libpldm/base.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>
19 #include <iostream>
20 #include <memory>
21 
22 namespace pldm
23 {
24 using namespace pldm::responder::utils;
25 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
26 
27 namespace responder
28 {
29 namespace fs = std::filesystem;
30 
31 namespace dma
32 {
33 /** @struct AspeedXdmaOp
34  *
35  * Structure representing XDMA operation
36  */
37 struct AspeedXdmaOp
38 {
39     uint64_t hostAddr; //!< the DMA address on the host side, configured by
40                        //!< PCI subsystem.
41     uint32_t len;      //!< the size of the transfer in bytes, it should be a
42                        //!< multiple of 16 bytes
43     uint32_t upstream; //!< boolean indicating the direction of the DMA
44                        //!< operation, true means a transfer from BMC to host.
45 };
46 
47 constexpr auto xdmaDev = "/dev/aspeed-xdma";
48 
49 int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address)
50 {
51     static const size_t pageSize = getpagesize();
52     uint32_t numPages = length / pageSize;
53     uint32_t pageAlignedLength = numPages * pageSize;
54 
55     if (length > pageAlignedLength)
56     {
57         pageAlignedLength += pageSize;
58     }
59 
60     auto mmapCleanup = [pageAlignedLength](void* vgaMem) {
61         munmap(vgaMem, pageAlignedLength);
62     };
63 
64     int dmaFd = -1;
65     int rc = 0;
66     dmaFd = open(xdmaDev, O_RDWR);
67     if (dmaFd < 0)
68     {
69         rc = -errno;
70         std::cerr << "transferHostDataToSocket: Failed to open the XDMA device,"
71                      " RC="
72                   << rc << "\n";
73         return rc;
74     }
75 
76     pldm::utils::CustomFD xdmaFd(dmaFd);
77 
78     void* vgaMem;
79     vgaMem =
80         mmap(nullptr, pageAlignedLength, PROT_READ, MAP_SHARED, xdmaFd(), 0);
81     if (MAP_FAILED == vgaMem)
82     {
83         rc = -errno;
84         std::cerr << "transferHostDataToSocket: Failed to mmap the XDMA device,"
85                      " RC="
86                   << rc << "\n";
87         return rc;
88     }
89 
90     std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
91 
92     AspeedXdmaOp xdmaOp;
93     xdmaOp.upstream = 0;
94     xdmaOp.hostAddr = address;
95     xdmaOp.len = length;
96 
97     rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
98     if (rc < 0)
99     {
100         rc = -errno;
101         std::cerr << "transferHostDataToSocket: Failed to execute the DMA "
102                      "operation, RC="
103                   << rc << " ADDRESS=" << address << " LENGTH=" << length
104                   << "\n";
105         return rc;
106     }
107 
108     rc = writeToUnixSocket(fd, static_cast<const char*>(vgaMemPtr.get()),
109                            length);
110     if (rc < 0)
111     {
112         rc = -errno;
113         close(fd);
114         std::cerr << "transferHostDataToSocket: Closing socket as "
115                      "writeToUnixSocket faile with RC="
116                   << rc << std::endl;
117         return rc;
118     }
119     return 0;
120 }
121 
122 int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length,
123                           uint64_t address, bool upstream)
124 {
125     static const size_t pageSize = getpagesize();
126     uint32_t numPages = length / pageSize;
127     uint32_t pageAlignedLength = numPages * pageSize;
128 
129     if (length > pageAlignedLength)
130     {
131         pageAlignedLength += pageSize;
132     }
133 
134     int rc = 0;
135     auto mmapCleanup = [pageAlignedLength, &rc](void* vgaMem) {
136         if (rc != -EINTR)
137         {
138             munmap(vgaMem, pageAlignedLength);
139         }
140         else
141         {
142             std::cerr
143                 << "transferDataHost: Received interrupt during DMA transfer."
144                    " Skipping Unmap."
145                 << std::endl;
146         }
147     };
148 
149     int dmaFd = -1;
150     dmaFd = open(xdmaDev, O_RDWR);
151     if (dmaFd < 0)
152     {
153         rc = -errno;
154         std::cerr << "transferDataHost: Failed to open the XDMA device, RC="
155                   << rc << "\n";
156         return rc;
157     }
158 
159     pldm::utils::CustomFD xdmaFd(dmaFd);
160 
161     void* vgaMem;
162     vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ,
163                   MAP_SHARED, xdmaFd(), 0);
164     if (MAP_FAILED == vgaMem)
165     {
166         rc = -errno;
167         std::cerr << "transferDataHost: Failed to mmap the XDMA device, RC="
168                   << rc << "\n";
169         return rc;
170     }
171 
172     std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
173 
174     if (upstream)
175     {
176         rc = lseek(fd, offset, SEEK_SET);
177         if (rc == -1)
178         {
179             std::cerr << "transferDataHost upstream: lseek failed, ERROR="
180                       << errno << ", UPSTREAM=" << upstream
181                       << ", OFFSET=" << offset << "\n";
182             return rc;
183         }
184 
185         // Writing to the VGA memory should be aligned at page boundary,
186         // otherwise write data into a buffer aligned at page boundary and
187         // then write to the VGA memory.
188         std::vector<char> buffer{};
189         buffer.resize(pageAlignedLength);
190         rc = read(fd, buffer.data(), length);
191         if (rc == -1)
192         {
193             std::cerr << "transferDataHost upstream: file read failed, ERROR="
194                       << errno << ", UPSTREAM=" << upstream
195                       << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
196             return rc;
197         }
198         if (rc != static_cast<int>(length))
199         {
200             std::cerr << "transferDataHost upstream: mismatch between number of"
201                       << "characters to read and the length read, LENGTH="
202                       << length << " COUNT=" << rc << "\n";
203             return -1;
204         }
205         memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(),
206                pageAlignedLength);
207     }
208 
209     AspeedXdmaOp xdmaOp;
210     xdmaOp.upstream = upstream ? 1 : 0;
211     xdmaOp.hostAddr = address;
212     xdmaOp.len = length;
213 
214     rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp));
215     if (rc < 0)
216     {
217         rc = -errno;
218         std::cerr << "transferDataHost: Failed to execute the DMA operation,"
219                      " RC="
220                   << rc << " UPSTREAM=" << upstream << " ADDRESS=" << address
221                   << " LENGTH=" << length << "\n";
222         return rc;
223     }
224 
225     if (!upstream)
226     {
227         rc = lseek(fd, offset, SEEK_SET);
228         if (rc == -1)
229         {
230             std::cerr << "transferDataHost downstream: lseek failed, ERROR="
231                       << errno << ", UPSTREAM=" << upstream
232                       << ", OFFSET=" << offset << "\n";
233             return rc;
234         }
235         rc = write(fd, static_cast<const char*>(vgaMemPtr.get()), length);
236         if (rc == -1)
237         {
238             std::cerr << "transferDataHost downstream: file write failed,"
239                          " ERROR="
240                       << errno << ", UPSTREAM=" << upstream
241                       << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
242             return rc;
243         }
244     }
245 
246     return 0;
247 }
248 
249 } // namespace dma
250 
251 namespace oem_ibm
252 {
253 Response Handler::readFileIntoMemory(const pldm_msg* request,
254                                      size_t payloadLength)
255 {
256     uint32_t fileHandle = 0;
257     uint32_t offset = 0;
258     uint32_t length = 0;
259     uint64_t address = 0;
260 
261     Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0);
262     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
263 
264     if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
265     {
266         encode_rw_file_memory_resp(request->hdr.instance_id,
267                                    PLDM_READ_FILE_INTO_MEMORY,
268                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
269         return response;
270     }
271 
272     decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
273                               &length, &address);
274 
275     using namespace pldm::filetable;
276     auto& table = buildFileTable(FILE_TABLE_JSON);
277     FileEntry value{};
278 
279     try
280     {
281         value = table.at(fileHandle);
282     }
283     catch (const std::exception& e)
284     {
285         std::cerr << "File handle does not exist in the file table, HANDLE="
286                   << fileHandle << "\n";
287         encode_rw_file_memory_resp(request->hdr.instance_id,
288                                    PLDM_READ_FILE_INTO_MEMORY,
289                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
290         return response;
291     }
292 
293     if (!fs::exists(value.fsPath))
294     {
295         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
296         encode_rw_file_memory_resp(request->hdr.instance_id,
297                                    PLDM_READ_FILE_INTO_MEMORY,
298                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
299         return response;
300     }
301 
302     auto fileSize = fs::file_size(value.fsPath);
303     if (offset >= fileSize)
304     {
305         std::cerr << "Offset exceeds file size, OFFSET=" << offset
306                   << " FILE_SIZE=" << fileSize << "\n";
307         encode_rw_file_memory_resp(request->hdr.instance_id,
308                                    PLDM_READ_FILE_INTO_MEMORY,
309                                    PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
310         return response;
311     }
312 
313     if (offset + length > fileSize)
314     {
315         length = fileSize - offset;
316     }
317 
318     if (length % dma::minSize)
319     {
320         std::cerr << "Read length is not a multiple of DMA minSize, LENGTH="
321                   << length << "\n";
322         encode_rw_file_memory_resp(request->hdr.instance_id,
323                                    PLDM_READ_FILE_INTO_MEMORY,
324                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
325         return response;
326     }
327 
328     using namespace dma;
329     DMA intf;
330     return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath,
331                             offset, length, address, true,
332                             request->hdr.instance_id);
333 }
334 
335 Response Handler::writeFileFromMemory(const pldm_msg* request,
336                                       size_t payloadLength)
337 {
338     uint32_t fileHandle = 0;
339     uint32_t offset = 0;
340     uint32_t length = 0;
341     uint64_t address = 0;
342 
343     Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0);
344     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
345 
346     if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES)
347     {
348         encode_rw_file_memory_resp(request->hdr.instance_id,
349                                    PLDM_WRITE_FILE_FROM_MEMORY,
350                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
351         return response;
352     }
353 
354     decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
355                               &length, &address);
356 
357     if (length % dma::minSize)
358     {
359         std::cerr << "Write length is not a multiple of DMA minSize, LENGTH="
360                   << length << "\n";
361         encode_rw_file_memory_resp(request->hdr.instance_id,
362                                    PLDM_WRITE_FILE_FROM_MEMORY,
363                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
364         return response;
365     }
366 
367     using namespace pldm::filetable;
368     auto& table = buildFileTable(FILE_TABLE_JSON);
369     FileEntry value{};
370 
371     try
372     {
373         value = table.at(fileHandle);
374     }
375     catch (const std::exception& e)
376     {
377         std::cerr << "File handle does not exist in the file table, HANDLE="
378                   << fileHandle << "\n";
379         encode_rw_file_memory_resp(request->hdr.instance_id,
380                                    PLDM_WRITE_FILE_FROM_MEMORY,
381                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
382         return response;
383     }
384 
385     if (!fs::exists(value.fsPath))
386     {
387         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
388         encode_rw_file_memory_resp(request->hdr.instance_id,
389                                    PLDM_WRITE_FILE_FROM_MEMORY,
390                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
391         return response;
392     }
393 
394     auto fileSize = fs::file_size(value.fsPath);
395     if (offset >= fileSize)
396     {
397         std::cerr << "Offset exceeds file size, OFFSET=" << offset
398                   << " FILE_SIZE=" << fileSize << "\n";
399         encode_rw_file_memory_resp(request->hdr.instance_id,
400                                    PLDM_WRITE_FILE_FROM_MEMORY,
401                                    PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
402         return response;
403     }
404 
405     using namespace dma;
406     DMA intf;
407     return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath,
408                             offset, length, address, false,
409                             request->hdr.instance_id);
410 }
411 
412 Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength)
413 {
414     uint32_t transferHandle = 0;
415     uint8_t transferFlag = 0;
416     uint8_t tableType = 0;
417 
418     Response response(sizeof(pldm_msg_hdr) +
419                       PLDM_GET_FILE_TABLE_MIN_RESP_BYTES);
420     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
421 
422     if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES)
423     {
424         encode_get_file_table_resp(request->hdr.instance_id,
425                                    PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0,
426                                    responsePtr);
427         return response;
428     }
429 
430     auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle,
431                                         &transferFlag, &tableType);
432     if (rc)
433     {
434         encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr,
435                                    0, responsePtr);
436         return response;
437     }
438 
439     if (tableType != PLDM_FILE_ATTRIBUTE_TABLE)
440     {
441         encode_get_file_table_resp(request->hdr.instance_id,
442                                    PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr,
443                                    0, responsePtr);
444         return response;
445     }
446 
447     using namespace pldm::filetable;
448     auto table = buildFileTable(FILE_TABLE_JSON);
449     auto attrTable = table();
450     response.resize(response.size() + attrTable.size());
451     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
452 
453     if (attrTable.empty())
454     {
455         encode_get_file_table_resp(request->hdr.instance_id,
456                                    PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr,
457                                    0, responsePtr);
458         return response;
459     }
460 
461     encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
462                                PLDM_START_AND_END, attrTable.data(),
463                                attrTable.size(), responsePtr);
464     return response;
465 }
466 
467 Response Handler::readFile(const pldm_msg* request, size_t payloadLength)
468 {
469     uint32_t fileHandle = 0;
470     uint32_t offset = 0;
471     uint32_t length = 0;
472 
473     Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES);
474     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
475 
476     if (payloadLength != PLDM_READ_FILE_REQ_BYTES)
477     {
478         encode_read_file_resp(request->hdr.instance_id,
479                               PLDM_ERROR_INVALID_LENGTH, length, responsePtr);
480         return response;
481     }
482 
483     auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset,
484                                    &length);
485 
486     if (rc)
487     {
488         encode_read_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 (const std::exception& e)
501     {
502         std::cerr << "File handle does not exist in the file table, HANDLE="
503                   << fileHandle << "\n";
504         encode_read_file_resp(request->hdr.instance_id,
505                               PLDM_INVALID_FILE_HANDLE, length, responsePtr);
506         return response;
507     }
508 
509     if (!fs::exists(value.fsPath))
510     {
511         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
512         encode_read_file_resp(request->hdr.instance_id,
513                               PLDM_INVALID_FILE_HANDLE, length, responsePtr);
514         return response;
515     }
516 
517     auto fileSize = fs::file_size(value.fsPath);
518     if (offset >= fileSize)
519     {
520         std::cerr << "Offset exceeds file size, OFFSET=" << offset
521                   << " FILE_SIZE=" << fileSize << "\n";
522         encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
523                               length, responsePtr);
524         return response;
525     }
526 
527     if (offset + length > fileSize)
528     {
529         length = fileSize - offset;
530     }
531 
532     response.resize(response.size() + length);
533     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
534     auto fileDataPos = reinterpret_cast<char*>(responsePtr);
535     fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length);
536 
537     std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary);
538     stream.seekg(offset);
539     stream.read(fileDataPos, length);
540 
541     encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
542                           responsePtr);
543 
544     return response;
545 }
546 
547 Response Handler::writeFile(const pldm_msg* request, size_t payloadLength)
548 {
549     uint32_t fileHandle = 0;
550     uint32_t offset = 0;
551     uint32_t length = 0;
552     size_t fileDataOffset = 0;
553 
554     Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES);
555     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
556 
557     if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES)
558     {
559         encode_write_file_resp(request->hdr.instance_id,
560                                PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
561         return response;
562     }
563 
564     auto rc = decode_write_file_req(request, payloadLength, &fileHandle,
565                                     &offset, &length, &fileDataOffset);
566 
567     if (rc)
568     {
569         encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr);
570         return response;
571     }
572 
573     using namespace pldm::filetable;
574     auto& table = buildFileTable(FILE_TABLE_JSON);
575     FileEntry value{};
576 
577     try
578     {
579         value = table.at(fileHandle);
580     }
581     catch (const std::exception& e)
582     {
583         std::cerr << "File handle does not exist in the file table, HANDLE="
584                   << fileHandle << "\n";
585         encode_write_file_resp(request->hdr.instance_id,
586                                PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
587         return response;
588     }
589 
590     if (!fs::exists(value.fsPath))
591     {
592         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
593         encode_write_file_resp(request->hdr.instance_id,
594                                PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
595         return response;
596     }
597 
598     auto fileSize = fs::file_size(value.fsPath);
599     if (offset >= fileSize)
600     {
601         std::cerr << "Offset exceeds file size, OFFSET=" << offset
602                   << " FILE_SIZE=" << fileSize << "\n";
603         encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE,
604                                0, responsePtr);
605         return response;
606     }
607 
608     auto fileDataPos =
609         reinterpret_cast<const char*>(request->payload) + fileDataOffset;
610 
611     std::ofstream stream(value.fsPath,
612                          std::ios::in | std::ios::out | std::ios::binary);
613     stream.seekp(offset);
614     stream.write(fileDataPos, length);
615 
616     encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length,
617                            responsePtr);
618 
619     return response;
620 }
621 
622 Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
623                                 size_t payloadLength,
624                                 oem_platform::Handler* oemPlatformHandler)
625 {
626     Response response(
627         sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
628     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
629 
630     if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES)
631     {
632         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
633                                            PLDM_ERROR_INVALID_LENGTH, 0,
634                                            responsePtr);
635         return response;
636     }
637 
638     uint16_t fileType{};
639     uint32_t fileHandle{};
640     uint32_t offset{};
641     uint32_t length{};
642     uint64_t address{};
643     auto rc = decode_rw_file_by_type_memory_req(request, payloadLength,
644                                                 &fileType, &fileHandle, &offset,
645                                                 &length, &address);
646     if (rc != PLDM_SUCCESS)
647     {
648         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
649                                            responsePtr);
650         return response;
651     }
652     if (length % dma::minSize)
653     {
654         std::cerr << "Length is not a multiple of DMA minSize, LENGTH="
655                   << length << "\n";
656         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
657                                            PLDM_ERROR_INVALID_LENGTH, 0,
658                                            responsePtr);
659         return response;
660     }
661 
662     std::unique_ptr<FileHandler> handler{};
663     try
664     {
665         handler = getHandlerByType(fileType, fileHandle);
666     }
667     catch (const InternalFailure& e)
668     {
669         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
670         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
671                                            PLDM_INVALID_FILE_TYPE, 0,
672                                            responsePtr);
673         return response;
674     }
675 
676     rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
677              ? handler->writeFromMemory(offset, length, address,
678                                         oemPlatformHandler)
679              : handler->readIntoMemory(offset, length, address,
680                                        oemPlatformHandler);
681     encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
682                                        length, responsePtr);
683     return response;
684 }
685 
686 Response Handler::writeFileByTypeFromMemory(const pldm_msg* request,
687                                             size_t payloadLength)
688 {
689     return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
690                                   payloadLength, oemPlatformHandler);
691 }
692 
693 Response Handler::readFileByTypeIntoMemory(const pldm_msg* request,
694                                            size_t payloadLength)
695 {
696     return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
697                                   payloadLength, oemPlatformHandler);
698 }
699 
700 Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength)
701 {
702     Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
703     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
704 
705     if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
706     {
707         encode_rw_file_by_type_resp(request->hdr.instance_id,
708                                     PLDM_WRITE_FILE_BY_TYPE,
709                                     PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
710         return response;
711     }
712     uint16_t fileType{};
713     uint32_t fileHandle{};
714     uint32_t offset{};
715     uint32_t length{};
716 
717     auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
718                                          &fileHandle, &offset, &length);
719     if (rc != PLDM_SUCCESS)
720     {
721         encode_rw_file_by_type_resp(request->hdr.instance_id,
722                                     PLDM_WRITE_FILE_BY_TYPE, rc, 0,
723                                     responsePtr);
724         return response;
725     }
726 
727     std::unique_ptr<FileHandler> handler{};
728     try
729     {
730         handler = getHandlerByType(fileType, fileHandle);
731     }
732     catch (const InternalFailure& e)
733     {
734         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
735         encode_rw_file_by_type_resp(request->hdr.instance_id,
736                                     PLDM_WRITE_FILE_BY_TYPE,
737                                     PLDM_INVALID_FILE_TYPE, 0, responsePtr);
738         return response;
739     }
740 
741     rc = handler->write(reinterpret_cast<const char*>(
742                             request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES),
743                         offset, length, oemPlatformHandler);
744     encode_rw_file_by_type_resp(request->hdr.instance_id,
745                                 PLDM_WRITE_FILE_BY_TYPE, rc, length,
746                                 responsePtr);
747     return response;
748 }
749 
750 Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength)
751 {
752     Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
753     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
754 
755     if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
756     {
757         encode_rw_file_by_type_resp(request->hdr.instance_id,
758                                     PLDM_READ_FILE_BY_TYPE,
759                                     PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
760         return response;
761     }
762     uint16_t fileType{};
763     uint32_t fileHandle{};
764     uint32_t offset{};
765     uint32_t length{};
766 
767     auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
768                                          &fileHandle, &offset, &length);
769     if (rc != PLDM_SUCCESS)
770     {
771         encode_rw_file_by_type_resp(request->hdr.instance_id,
772                                     PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr);
773         return response;
774     }
775 
776     std::unique_ptr<FileHandler> handler{};
777     try
778     {
779         handler = getHandlerByType(fileType, fileHandle);
780     }
781     catch (const InternalFailure& e)
782     {
783         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
784         encode_rw_file_by_type_resp(request->hdr.instance_id,
785                                     PLDM_READ_FILE_BY_TYPE,
786                                     PLDM_INVALID_FILE_TYPE, 0, responsePtr);
787         return response;
788     }
789 
790     rc = handler->read(offset, length, response, oemPlatformHandler);
791     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
792     encode_rw_file_by_type_resp(request->hdr.instance_id,
793                                 PLDM_READ_FILE_BY_TYPE, rc, length,
794                                 responsePtr);
795     return response;
796 }
797 
798 Response Handler::fileAck(const pldm_msg* request, size_t payloadLength)
799 {
800     Response response(sizeof(pldm_msg_hdr) + PLDM_FILE_ACK_RESP_BYTES);
801     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
802 
803     if (payloadLength != PLDM_FILE_ACK_REQ_BYTES)
804     {
805         encode_file_ack_resp(request->hdr.instance_id,
806                              PLDM_ERROR_INVALID_LENGTH, responsePtr);
807         return response;
808     }
809     uint16_t fileType{};
810     uint32_t fileHandle{};
811     uint8_t fileStatus{};
812 
813     auto rc = decode_file_ack_req(request, payloadLength, &fileType,
814                                   &fileHandle, &fileStatus);
815     if (rc != PLDM_SUCCESS)
816     {
817         encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr);
818         return response;
819     }
820 
821     std::unique_ptr<FileHandler> handler{};
822     try
823     {
824         handler = getHandlerByType(fileType, fileHandle);
825     }
826 
827     catch (const InternalFailure& e)
828     {
829         encode_file_ack_resp(request->hdr.instance_id, PLDM_INVALID_FILE_TYPE,
830                              responsePtr);
831         return response;
832     }
833 
834     rc = handler->fileAck(fileStatus);
835     encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr);
836     return response;
837 }
838 
839 Response Handler::getAlertStatus(const pldm_msg* request, size_t payloadLength)
840 {
841     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_ALERT_STATUS_RESP_BYTES);
842     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
843     if (payloadLength != PLDM_GET_ALERT_STATUS_REQ_BYTES)
844     {
845         return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
846     }
847 
848     uint8_t versionId{};
849 
850     auto rc = decode_get_alert_status_req(request, payloadLength, &versionId);
851     if (rc != PLDM_SUCCESS)
852     {
853         return CmdHandler::ccOnlyResponse(request, rc);
854     }
855 
856     if (versionId != 0)
857     {
858         return CmdHandler::ccOnlyResponse(request,
859                                           PLDM_HOST_UNSUPPORTED_FORMAT_VERSION);
860     }
861 
862     constexpr uint32_t rackEntry = 0xFF000030;
863     constexpr uint32_t priCecNode = 0x00008030;
864     rc = encode_get_alert_status_resp(request->hdr.instance_id, PLDM_SUCCESS,
865                                       rackEntry, priCecNode, responsePtr,
866                                       PLDM_GET_ALERT_STATUS_RESP_BYTES);
867     if (rc != PLDM_SUCCESS)
868     {
869         return CmdHandler::ccOnlyResponse(request, rc);
870     }
871 
872     return response;
873 }
874 
875 Response Handler::newFileAvailable(const pldm_msg* request,
876                                    size_t payloadLength)
877 {
878     Response response(sizeof(pldm_msg_hdr) + PLDM_NEW_FILE_RESP_BYTES);
879 
880     if (payloadLength != PLDM_NEW_FILE_REQ_BYTES)
881     {
882         return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
883     }
884     uint16_t fileType{};
885     uint32_t fileHandle{};
886     uint64_t length{};
887 
888     auto rc = decode_new_file_req(request, payloadLength, &fileType,
889                                   &fileHandle, &length);
890 
891     if (rc != PLDM_SUCCESS)
892     {
893         return CmdHandler::ccOnlyResponse(request, rc);
894     }
895 
896     std::unique_ptr<FileHandler> handler{};
897     try
898     {
899         handler = getHandlerByType(fileType, fileHandle);
900     }
901     catch (const InternalFailure& e)
902     {
903         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
904         return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE);
905     }
906 
907     rc = handler->newFileAvailable(length);
908     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
909     encode_new_file_resp(request->hdr.instance_id, rc, responsePtr);
910     return response;
911 }
912 
913 } // namespace oem_ibm
914 } // namespace responder
915 } // namespace pldm
916