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
diff --git a/oem/meta/libpldmresponder/file_io.hpp b/oem/meta/libpldmresponder/file_io.hpp
new file mode 100644
index 0000000..510d650
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io.hpp
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "common/utils.hpp"
+#include "file_io_by_type.hpp"
+#include "pldmd/handler.hpp"
+
+#include <libpldm/oem/meta/file_io.h>
+
+#include <phosphor-logging/lg2.hpp>
+
+PHOSPHOR_LOG2_USING;
+
+namespace pldm::responder::oem_meta
+{
+
+class FileIOHandler : public CmdHandler
+{
+ public:
+ FileIOHandler()
+ {
+ handlers.emplace(
+ PLDM_OEM_META_FILE_IO_CMD_WRITE_FILE,
+ [this](pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength) {
+ return this->writeFileIO(tid, request, payloadLength);
+ });
+ handlers.emplace(
+ PLDM_OEM_META_FILE_IO_CMD_READ_FILE,
+ [this](pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength) {
+ return this->readFileIO(tid, request, payloadLength);
+ });
+ }
+
+ FileIOHandler(const FileIOHandler&) = delete;
+ FileIOHandler(FileIOHandler&&) = delete;
+ FileIOHandler& operator=(const FileIOHandler&) = delete;
+ FileIOHandler& operator=(FileIOHandler&&) = delete;
+ virtual ~FileIOHandler() = default;
+
+ private:
+ /** @brief Handler for writeFileIO command
+ *
+ * @param[in] tid - the device tid
+ * @param[in] request - pointer to PLDM request payload
+ * @param[in] payloadLength - length of the message
+ *
+ * @return PLDM response message
+ */
+ Response writeFileIO(pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength);
+
+ /** @brief Handler for readFileIO command
+ *
+ * @param[in] tid - the device tid
+ * @param[in] request - pointer to PLDM request payload
+ * @param[in] payloadLength - length of the message
+ *
+ * @return PLDM response message
+ */
+ Response readFileIO(pldm_tid_t tid, const pldm_msg* request,
+ size_t payloadLength);
+
+ std::unique_ptr<FileHandler> getHandlerByType(pldm_tid_t tid,
+ FileIOType fileIOType);
+};
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/file_io_by_type.hpp b/oem/meta/libpldmresponder/file_io_by_type.hpp
new file mode 100644
index 0000000..c8e7d05
--- /dev/null
+++ b/oem/meta/libpldmresponder/file_io_by_type.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <libpldm/base.h>
+#include <libpldm/oem/meta/file_io.h>
+
+#include <cstdint>
+#include <span>
+
+namespace pldm::responder::oem_meta
+{
+using message = std::span<uint8_t>;
+
+enum class FileIOType : uint8_t
+{
+};
+
+/**
+ * @class FileHandler
+ *
+ * Base class to handle read/write of all OEM file types
+ */
+class FileHandler
+{
+ protected:
+ FileHandler() = default;
+
+ public:
+ FileHandler(const FileHandler&) = delete;
+ FileHandler(FileHandler&&) = delete;
+ FileHandler& operator=(const FileHandler&) = delete;
+ FileHandler& operator=(FileHandler&&) = delete;
+ virtual ~FileHandler() = default;
+
+ /** @brief Method to write data to BMC
+ * @param[in] data - eventData
+ * @return PLDM status code
+ */
+ virtual int write([[maybe_unused]] const message& data)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+
+ /** @brief Method to read data from BIC
+ * @param[in] data - eventData
+ * @return PLDM status code
+ */
+ virtual int read(
+ [[maybe_unused]] struct pldm_oem_meta_file_io_read_resp* data)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+};
+
+} // namespace pldm::responder::oem_meta
diff --git a/oem/meta/libpldmresponder/meson.build b/oem/meta/libpldmresponder/meson.build
new file mode 100644
index 0000000..5494ada
--- /dev/null
+++ b/oem/meta/libpldmresponder/meson.build
@@ -0,0 +1 @@
+oem_files += files('file_io.cpp')
diff --git a/oem/meta/meson.build b/oem/meta/meson.build
index 13d3a8e..b4fc15e 100644
--- a/oem/meta/meson.build
+++ b/oem/meta/meson.build
@@ -1,3 +1,4 @@
oem_files += files('oem_meta.cpp', 'utils.cpp')
+subdir('libpldmresponder')
subdir('event')
diff --git a/oem/meta/oem_meta.cpp b/oem/meta/oem_meta.cpp
index 540b334..661fa95 100644
--- a/oem/meta/oem_meta.cpp
+++ b/oem/meta/oem_meta.cpp
@@ -1,15 +1,21 @@
-
#include "oem_meta.hpp"
#include <libpldm/base.h>
+#include <utility>
+
namespace pldm::oem_meta
{
-OemMETA::OemMETA(pldm::responder::platform::Handler* platformHandler)
+OemMETA::OemMETA(pldm::responder::Invoker& invoker,
+ pldm::responder::platform::Handler* platformHandler)
{
oemEventManager = std::make_unique<oem_meta::OemEventManager>();
registerOemEventHandler(platformHandler);
+
+ auto fileIOHandler =
+ std::make_unique<pldm::responder::oem_meta::FileIOHandler>();
+ registerOemHandler(invoker, std::move(fileIOHandler));
}
void OemMETA::registerOemEventHandler(
@@ -24,4 +30,11 @@
}});
}
+void OemMETA::registerOemHandler(
+ pldm::responder::Invoker& invoker,
+ std::unique_ptr<pldm::responder::oem_meta::FileIOHandler> fileIOHandler)
+{
+ invoker.registerHandler(PLDM_OEM, std::move(fileIOHandler));
+}
+
} // namespace pldm::oem_meta
diff --git a/oem/meta/oem_meta.hpp b/oem/meta/oem_meta.hpp
index 266a8bf..df67367 100644
--- a/oem/meta/oem_meta.hpp
+++ b/oem/meta/oem_meta.hpp
@@ -2,6 +2,8 @@
#include "libpldmresponder/platform.hpp"
#include "oem/meta/event/oem_event_manager.hpp"
+#include "oem/meta/libpldmresponder/file_io.hpp"
+#include "pldmd/invoker.hpp"
namespace pldm::oem_meta
{
@@ -24,14 +26,21 @@
public:
/** @brief Constucts OemMETA object
+ * @param[in] invoker - invoker handler
* @param[in] platformHandler - platformHandler handler
*/
- explicit OemMETA(pldm::responder::platform::Handler* platformHandler);
+ explicit OemMETA(pldm::responder::Invoker& invoker,
+ pldm::responder::platform::Handler* platformHandler);
private:
void registerOemEventHandler(
pldm::responder::platform::Handler* platformHandler);
+ void registerOemHandler(
+ pldm::responder::Invoker& invoker,
+ std::unique_ptr<pldm::responder::oem_meta::FileIOHandler>
+ fileIOHandler);
+
std::unique_ptr<oem_meta::OemEventManager> oemEventManager{};
};