oem-ibm: implement WriteFileByTypeFromMemory handler
This commit implements a framework for handling oem file types
received to/from host. Along with that it also implements the responder
for oem command WriteFileByTypeFromMemory and processes PELs received
from the host firmware.
Change-Id: Ice866aed0343b90769013c4be31a0c730f6e6bcd
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp
index 64b020b..692ae1b 100644
--- a/oem/ibm/libpldmresponder/file_io.cpp
+++ b/oem/ibm/libpldmresponder/file_io.cpp
@@ -2,9 +2,11 @@
#include "file_io.hpp"
+#include "file_io_by_type.hpp"
#include "file_table.hpp"
#include "libpldmresponder/utils.hpp"
#include "registration.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
#include <fcntl.h>
#include <sys/mman.h>
@@ -14,6 +16,8 @@
#include <cstring>
#include <fstream>
+#include <memory>
+#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include "libpldm/base.h"
@@ -21,6 +25,9 @@
namespace pldm
{
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+
namespace responder
{
@@ -36,6 +43,8 @@
std::move(writeFileFromMemory));
registerHandler(PLDM_OEM, PLDM_READ_FILE, std::move(readFile));
registerHandler(PLDM_OEM, PLDM_WRITE_FILE, std::move(writeFile));
+ registerHandler(PLDM_OEM, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
+ std::move(writeFileByTypeFromMemory));
}
} // namespace oem_ibm
@@ -144,8 +153,12 @@
if (!upstream)
{
- std::ofstream stream(path.string(),
- std::ios::in | std::ios::out | std::ios::binary);
+ std::ios_base::openmode mode = std::ios::out | std::ios::binary;
+ if (fs::exists(path))
+ {
+ mode |= std::ios::in;
+ }
+ std::ofstream stream(path.string(), mode);
stream.seekp(offset);
stream.write(static_cast<const char*>(vgaMemPtr.get()), length);
@@ -523,5 +536,66 @@
return response;
}
+Response writeFileByTypeFromMemory(const pldm_msg* request,
+ size_t payloadLength)
+{
+ Response response(
+ sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+ if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES)
+ {
+ encode_rw_file_by_type_memory_resp(
+ request->hdr.instance_id, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
+ PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
+ return response;
+ }
+
+ uint16_t fileType{};
+ uint32_t fileHandle{};
+ uint32_t offset{};
+ uint32_t length{};
+ uint64_t address{};
+ auto rc = decode_rw_file_by_type_memory_req(request, payloadLength,
+ &fileType, &fileHandle, &offset,
+ &length, &address);
+ if (rc != PLDM_SUCCESS)
+ {
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id,
+ PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
+ rc, 0, responsePtr);
+ return response;
+ }
+ if (length % dma::minSize)
+ {
+ log<level::ERR>("Write length is not a multiple of DMA minSize",
+ entry("LENGTH=%d", length));
+ encode_rw_file_by_type_memory_resp(
+ request->hdr.instance_id, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
+ PLDM_INVALID_WRITE_LENGTH, 0, responsePtr);
+ return response;
+ }
+
+ std::unique_ptr<FileHandler> handler{};
+ try
+ {
+ handler = getHandlerByType(fileType, fileHandle);
+ }
+ catch (const InternalFailure& e)
+ {
+ log<level::ERR>("unknown file type ", entry("TYPE=%d", fileType));
+ encode_rw_file_by_type_memory_resp(
+ request->hdr.instance_id, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
+ PLDM_INVALID_FILE_TYPE, 0, responsePtr);
+ return response;
+ }
+
+ rc = handler->writeFromMemory(offset, length, address);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id,
+ PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, rc,
+ length, responsePtr);
+ return response;
+}
+
} // namespace responder
} // namespace pldm