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