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