1 #include "config.h"
2 
3 #include "file_io.hpp"
4 
5 #include "libpldm/base.h"
6 
7 #include "file_io_by_type.hpp"
8 #include "file_table.hpp"
9 #include "utils.hpp"
10 #include "xyz/openbmc_project/Common/error.hpp"
11 
12 #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>
20 #include <iostream>
21 #include <memory>
22 
23 namespace pldm
24 {
25 using namespace pldm::responder::utils;
26 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
27 
28 namespace responder
29 {
30 
31 namespace fs = std::filesystem;
32 
33 namespace dma
34 {
35 
36 /** @struct AspeedXdmaOp
37  *
38  * Structure representing XDMA operation
39  */
40 struct 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 
50 constexpr auto xdmaDev = "/dev/aspeed-xdma";
51 
52 int 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 
117 int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length,
118                           uint64_t address, bool upstream)
119 {
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 
129     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         }
141     };
142 
143     int dmaFd = -1;
144     dmaFd = open(xdmaDev, O_RDWR);
145     if (dmaFd < 0)
146     {
147         rc = -errno;
148         std::cerr << "Failed to open the XDMA device, RC=" << rc << "\n";
149         return rc;
150     }
151 
152     pldm::utils::CustomFD xdmaFd(dmaFd);
153 
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;
160         std::cerr << "Failed to mmap the XDMA device, RC=" << rc << "\n";
161         return rc;
162     }
163 
164     std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup);
165 
166     if (upstream)
167     {
168         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         }
176 
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);
182         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))
191         {
192             std::cerr << "mismatch between number of characters to read and "
193                       << "the length read, LENGTH=" << length << " COUNT=" << rc
194                       << "\n";
195             return -1;
196         }
197         memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(),
198                pageAlignedLength);
199     }
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;
210         std::cerr << "Failed to execute the DMA operation, RC=" << rc
211                   << " UPSTREAM=" << upstream << " ADDRESS=" << address
212                   << " LENGTH=" << length << "\n";
213         return rc;
214     }
215 
216     if (!upstream)
217     {
218         rc = lseek(fd, offset, SEEK_SET);
219         if (rc == -1)
220         {
221             std::cerr << "lseek failed, ERROR=" << errno
222                       << ", UPSTREAM=" << upstream << ", OFFSET=" << offset
223                       << "\n";
224             return rc;
225         }
226         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         }
234     }
235 
236     return 0;
237 }
238 
239 } // namespace dma
240 
241 namespace oem_ibm
242 {
243 
244 Response Handler::readFileIntoMemory(const pldm_msg* request,
245                                      size_t payloadLength)
246 {
247     uint32_t fileHandle = 0;
248     uint32_t offset = 0;
249     uint32_t length = 0;
250     uint64_t address = 0;
251 
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     {
257         encode_rw_file_memory_resp(request->hdr.instance_id,
258                                    PLDM_READ_FILE_INTO_MEMORY,
259                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
260         return response;
261     }
262 
263     decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
264                               &length, &address);
265 
266     using namespace pldm::filetable;
267     auto& table = buildFileTable(FILE_TABLE_JSON);
268     FileEntry value{};
269 
270     try
271     {
272         value = table.at(fileHandle);
273     }
274     catch (const std::exception& e)
275     {
276         std::cerr << "File handle does not exist in the file table, HANDLE="
277                   << fileHandle << "\n";
278         encode_rw_file_memory_resp(request->hdr.instance_id,
279                                    PLDM_READ_FILE_INTO_MEMORY,
280                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
281         return response;
282     }
283 
284     if (!fs::exists(value.fsPath))
285     {
286         std::cerr << "File does not exist, HANDLE=" << 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     auto fileSize = fs::file_size(value.fsPath);
294     if (offset >= fileSize)
295     {
296         std::cerr << "Offset exceeds file size, OFFSET=" << offset
297                   << " FILE_SIZE=" << fileSize << "\n";
298         encode_rw_file_memory_resp(request->hdr.instance_id,
299                                    PLDM_READ_FILE_INTO_MEMORY,
300                                    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     {
311         std::cerr << "Read length is not a multiple of DMA minSize, LENGTH="
312                   << length << "\n";
313         encode_rw_file_memory_resp(request->hdr.instance_id,
314                                    PLDM_READ_FILE_INTO_MEMORY,
315                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
316         return response;
317     }
318 
319     using namespace dma;
320     DMA intf;
321     return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath,
322                             offset, length, address, true,
323                             request->hdr.instance_id);
324 }
325 
326 Response Handler::writeFileFromMemory(const pldm_msg* request,
327                                       size_t payloadLength)
328 {
329     uint32_t fileHandle = 0;
330     uint32_t offset = 0;
331     uint32_t length = 0;
332     uint64_t address = 0;
333 
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     {
339         encode_rw_file_memory_resp(request->hdr.instance_id,
340                                    PLDM_WRITE_FILE_FROM_MEMORY,
341                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
342         return response;
343     }
344 
345     decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset,
346                               &length, &address);
347 
348     if (length % dma::minSize)
349     {
350         std::cerr << "Write length is not a multiple of DMA minSize, LENGTH="
351                   << length << "\n";
352         encode_rw_file_memory_resp(request->hdr.instance_id,
353                                    PLDM_WRITE_FILE_FROM_MEMORY,
354                                    PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
355         return response;
356     }
357 
358     using namespace pldm::filetable;
359     auto& table = buildFileTable(FILE_TABLE_JSON);
360     FileEntry value{};
361 
362     try
363     {
364         value = table.at(fileHandle);
365     }
366     catch (const std::exception& e)
367     {
368         std::cerr << "File handle does not exist in the file table, HANDLE="
369                   << fileHandle << "\n";
370         encode_rw_file_memory_resp(request->hdr.instance_id,
371                                    PLDM_WRITE_FILE_FROM_MEMORY,
372                                    PLDM_INVALID_FILE_HANDLE, 0, responsePtr);
373         return response;
374     }
375 
376     if (!fs::exists(value.fsPath))
377     {
378         std::cerr << "File does not exist, HANDLE=" << 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     auto fileSize = fs::file_size(value.fsPath);
386     if (offset >= fileSize)
387     {
388         std::cerr << "Offset exceeds file size, OFFSET=" << offset
389                   << " FILE_SIZE=" << fileSize << "\n";
390         encode_rw_file_memory_resp(request->hdr.instance_id,
391                                    PLDM_WRITE_FILE_FROM_MEMORY,
392                                    PLDM_DATA_OUT_OF_RANGE, 0, responsePtr);
393         return response;
394     }
395 
396     using namespace dma;
397     DMA intf;
398     return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath,
399                             offset, length, address, false,
400                             request->hdr.instance_id);
401 }
402 
403 Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength)
404 {
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     {
415         encode_get_file_table_resp(request->hdr.instance_id,
416                                    PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0,
417                                    responsePtr);
418         return response;
419     }
420 
421     auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle,
422                                         &transferFlag, &tableType);
423     if (rc)
424     {
425         encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr,
426                                    0, responsePtr);
427         return response;
428     }
429 
430     if (tableType != PLDM_FILE_ATTRIBUTE_TABLE)
431     {
432         encode_get_file_table_resp(request->hdr.instance_id,
433                                    PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr,
434                                    0, responsePtr);
435         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     {
446         encode_get_file_table_resp(request->hdr.instance_id,
447                                    PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr,
448                                    0, responsePtr);
449         return response;
450     }
451 
452     encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
453                                PLDM_START_AND_END, attrTable.data(),
454                                attrTable.size(), responsePtr);
455     return response;
456 }
457 
458 Response Handler::readFile(const pldm_msg* request, size_t payloadLength)
459 {
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     }
491     catch (const std::exception& e)
492     {
493         std::cerr << "File handle does not exist in the file table, HANDLE="
494                   << fileHandle << "\n";
495         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     {
502         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
503         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     {
511         std::cerr << "Offset exceeds file size, OFFSET=" << offset
512                   << " FILE_SIZE=" << fileSize << "\n";
513         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 
538 Response Handler::writeFile(const pldm_msg* request, size_t payloadLength)
539 {
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     }
572     catch (const std::exception& e)
573     {
574         std::cerr << "File handle does not exist in the file table, HANDLE="
575                   << fileHandle << "\n";
576         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     {
583         std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n";
584         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     {
592         std::cerr << "Offset exceeds file size, OFFSET=" << offset
593                   << " FILE_SIZE=" << fileSize << "\n";
594         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 
613 Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
614                                 size_t payloadLength,
615                                 oem_platform::Handler* oemPlatformHandler)
616 {
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     {
623         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
624                                            PLDM_ERROR_INVALID_LENGTH, 0,
625                                            responsePtr);
626         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     {
639         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
640                                            responsePtr);
641         return response;
642     }
643     if (length % dma::minSize)
644     {
645         std::cerr << "Length is not a multiple of DMA minSize, LENGTH="
646                   << length << "\n";
647         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
648                                            PLDM_ERROR_INVALID_LENGTH, 0,
649                                            responsePtr);
650         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     {
660         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
661         encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
662                                            PLDM_INVALID_FILE_TYPE, 0,
663                                            responsePtr);
664         return response;
665     }
666 
667     rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
668              ? handler->writeFromMemory(offset, length, address,
669                                         oemPlatformHandler)
670              : handler->readIntoMemory(offset, length, address,
671                                        oemPlatformHandler);
672     encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
673                                        length, responsePtr);
674     return response;
675 }
676 
677 Response Handler::writeFileByTypeFromMemory(const pldm_msg* request,
678                                             size_t payloadLength)
679 {
680     return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
681                                   payloadLength, oemPlatformHandler);
682 }
683 
684 Response Handler::readFileByTypeIntoMemory(const pldm_msg* request,
685                                            size_t payloadLength)
686 {
687     return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
688                                   payloadLength, oemPlatformHandler);
689 }
690 
691 Response 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 
696     if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
697     {
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*>(
733                             request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES),
734                         offset, length, oemPlatformHandler);
735     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 
741 Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength)
742 {
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     {
774         std::cerr << "unknown file type, TYPE=" << fileType << "\n";
775         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 
781     rc = handler->read(offset, length, response, oemPlatformHandler);
782     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
783     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 
789 Response 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     }
817 
818     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 
830 Response 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 
866 Response 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 
904 } // namespace oem_ibm
905 } // namespace responder
906 } // namespace pldm
907