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