oem-meta: Add file IO responder
Support handling file I/O request from BIC.
Tested: Verified in yosemite4 platform.
Change-Id: I4a630bffc5ab3fddea0618130d970b4c7ecf59f0
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
Signed-off-by: Sora Su <baxiche@gmail.com>
diff --git a/oem/meta/libpldmresponder/file_io.cpp b/oem/meta/libpldmresponder/file_io.cpp
new file mode 100644
index 0000000..e4800fb
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io.cpp
@@ -0,0 +1,132 @@
+#include "file_io.hpp"
+
+#include <libpldm/oem/meta/file_io.h>
+
+#include <filesystem>
+namespace pldm::responder::oem_meta
+{
+
+std::unique_ptr<FileHandler> FileIOHandler::getHandlerByType(
+ [[maybe_unused]] pldm_tid_t messageTid, FileIOType fileIOType)
+{
+ switch (fileIOType)
+ {
+ default:
+ error("Get invalid file io type {FILEIOTYPE}", "FILEIOTYPE",
+ fileIOType);
+ break;
+ }
+ return nullptr;
+}
+
+Response FileIOHandler::writeFileIO(pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength)
+{
+ static constexpr uint8_t decodeDataMaxLength = 240;
+ constexpr uint8_t decodereqlen =
+ PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH + decodeDataMaxLength;
+ alignas(struct pldm_oem_meta_file_io_write_req) unsigned char
+ reqbuf[decodereqlen];
+ auto request_msg = new (reqbuf) pldm_oem_meta_file_io_write_req;
+ auto request_data = static_cast<uint8_t*>(
+ pldm_oem_meta_file_io_write_req_data(request_msg));
+
+ int rc = decode_oem_meta_file_io_write_req(request, payloadLength,
+ request_msg, decodereqlen);
+
+ if (rc != 0)
+ {
+ error("Failed to decode OEM Meta write file IO request");
+ return ccOnlyResponse(request, rc);
+ }
+
+ auto handler =
+ getHandlerByType(tid, static_cast<FileIOType>(request_msg->handle));
+ if (!handler)
+ {
+ return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
+ }
+
+ auto data = std::span(request_data, request_msg->length);
+
+ rc = handler->write(data);
+
+ return ccOnlyResponse(request, rc);
+}
+
+Response FileIOHandler::readFileIO(pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength)
+{
+ int rc;
+ struct pldm_oem_meta_file_io_read_req request_msg = {};
+ request_msg.version = sizeof(struct pldm_oem_meta_file_io_read_req);
+
+ rc = decode_oem_meta_file_io_read_req(request, payloadLength, &request_msg);
+
+ if (rc != 0)
+ {
+ error("Failed to decode OEM Meta read file IO request");
+ return ccOnlyResponse(request, rc);
+ }
+
+ auto handler =
+ getHandlerByType(tid, static_cast<FileIOType>(request_msg.handle));
+
+ if (!handler)
+ {
+ return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
+ }
+
+ size_t encoderesplen = PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE;
+ if (request_msg.option == PLDM_OEM_META_FILE_IO_READ_ATTR)
+ {
+ encoderesplen += PLDM_OEM_META_FILE_IO_READ_ATTR_INFO_LENGTH;
+ }
+ else
+ {
+ encoderesplen += PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH;
+ }
+
+ std::vector<uint8_t> respbuf(
+ sizeof(struct pldm_oem_meta_file_io_read_resp) + request_msg.length);
+ auto* response_msg = new (respbuf.data()) pldm_oem_meta_file_io_read_resp;
+
+ response_msg->version = sizeof(struct pldm_oem_meta_file_io_read_resp);
+ response_msg->handle = request_msg.handle;
+ response_msg->option = request_msg.option;
+ response_msg->length = request_msg.length;
+
+ if (response_msg->option != PLDM_OEM_META_FILE_IO_READ_ATTR)
+ {
+ response_msg->info.data.transferFlag =
+ request_msg.info.data.transferFlag;
+ response_msg->info.data.offset = request_msg.info.data.offset;
+ }
+
+ rc = handler->read(response_msg);
+
+ if (rc != PLDM_SUCCESS)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ response_msg->completion_code = PLDM_SUCCESS;
+ encoderesplen += response_msg->length;
+
+ Response response(sizeof(pldm_msg_hdr) + encoderesplen, 0);
+ auto responseMsg = new (response.data()) pldm_msg;
+
+ rc = encode_oem_meta_file_io_read_resp(
+ request->hdr.instance_id, response_msg,
+ sizeof(struct pldm_oem_meta_file_io_read_resp) + response_msg->length,
+ responseMsg, encoderesplen);
+
+ if (rc != 0)
+ {
+ return ccOnlyResponse(request, rc);
+ }
+
+ return response;
+}
+
+} // namespace pldm::responder::oem_meta