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