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