xref: /openbmc/pldm/oem/meta/libpldmresponder/file_io.cpp (revision 972381fce00278066295f24f47d7e7df5aa68260)
1 #include "file_io.hpp"
2 
3 #include <libpldm/oem/meta/file_io.h>
4 
5 #include <filesystem>
6 namespace pldm::responder::oem_meta
7 {
8 
9 std::unique_ptr<FileHandler> FileIOHandler::getHandlerByType(
10     [[maybe_unused]] pldm_tid_t messageTid, FileIOType fileIOType)
11 {
12     switch (fileIOType)
13     {
14         default:
15             error("Get invalid file io type {FILEIOTYPE}", "FILEIOTYPE",
16                   fileIOType);
17             break;
18     }
19     return nullptr;
20 }
21 
22 Response FileIOHandler::writeFileIO(pldm_tid_t tid, const pldm_msg* request,
23                                     size_t payloadLength)
24 {
25     static constexpr uint8_t decodeDataMaxLength = 240;
26     constexpr uint8_t decodereqlen =
27         PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH + decodeDataMaxLength;
28     alignas(struct pldm_oem_meta_file_io_write_req) unsigned char
29         reqbuf[decodereqlen];
30     auto request_msg = new (reqbuf) pldm_oem_meta_file_io_write_req;
31     auto request_data = static_cast<uint8_t*>(
32         pldm_oem_meta_file_io_write_req_data(request_msg));
33 
34     int rc = decode_oem_meta_file_io_write_req(request, payloadLength,
35                                                request_msg, decodereqlen);
36 
37     if (rc != 0)
38     {
39         error("Failed to decode OEM Meta write file IO request");
40         return ccOnlyResponse(request, rc);
41     }
42 
43     auto handler =
44         getHandlerByType(tid, static_cast<FileIOType>(request_msg->handle));
45     if (!handler)
46     {
47         return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
48     }
49 
50     auto data = std::span(request_data, request_msg->length);
51 
52     rc = handler->write(data);
53 
54     return ccOnlyResponse(request, rc);
55 }
56 
57 Response FileIOHandler::readFileIO(pldm_tid_t tid, const pldm_msg* request,
58                                    size_t payloadLength)
59 {
60     int rc;
61     struct pldm_oem_meta_file_io_read_req request_msg = {};
62     request_msg.version = sizeof(struct pldm_oem_meta_file_io_read_req);
63 
64     rc = decode_oem_meta_file_io_read_req(request, payloadLength, &request_msg);
65 
66     if (rc != 0)
67     {
68         error("Failed to decode OEM Meta read file IO request");
69         return ccOnlyResponse(request, rc);
70     }
71 
72     auto handler =
73         getHandlerByType(tid, static_cast<FileIOType>(request_msg.handle));
74 
75     if (!handler)
76     {
77         return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
78     }
79 
80     size_t encoderesplen = PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE;
81     if (request_msg.option == PLDM_OEM_META_FILE_IO_READ_ATTR)
82     {
83         encoderesplen += PLDM_OEM_META_FILE_IO_READ_ATTR_INFO_LENGTH;
84     }
85     else
86     {
87         encoderesplen += PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH;
88     }
89 
90     std::vector<uint8_t> respbuf(
91         sizeof(struct pldm_oem_meta_file_io_read_resp) + request_msg.length);
92     auto* response_msg = new (respbuf.data()) pldm_oem_meta_file_io_read_resp;
93 
94     response_msg->version = sizeof(struct pldm_oem_meta_file_io_read_resp);
95     response_msg->handle = request_msg.handle;
96     response_msg->option = request_msg.option;
97     response_msg->length = request_msg.length;
98 
99     if (response_msg->option != PLDM_OEM_META_FILE_IO_READ_ATTR)
100     {
101         response_msg->info.data.transferFlag =
102             request_msg.info.data.transferFlag;
103         response_msg->info.data.offset = request_msg.info.data.offset;
104     }
105 
106     rc = handler->read(response_msg);
107 
108     if (rc != PLDM_SUCCESS)
109     {
110         return ccOnlyResponse(request, rc);
111     }
112 
113     response_msg->completion_code = PLDM_SUCCESS;
114     encoderesplen += response_msg->length;
115 
116     Response response(sizeof(pldm_msg_hdr) + encoderesplen, 0);
117     auto responseMsg = new (response.data()) pldm_msg;
118 
119     rc = encode_oem_meta_file_io_read_resp(
120         request->hdr.instance_id, response_msg,
121         sizeof(struct pldm_oem_meta_file_io_read_resp) + response_msg->length,
122         responseMsg, encoderesplen);
123 
124     if (rc != 0)
125     {
126         return ccOnlyResponse(request, rc);
127     }
128 
129     return response;
130 }
131 
132 } // namespace pldm::responder::oem_meta
133