oem-ibm: add readFileByType handler
Add a handler for file type 'LID', to be able to read LID files over the
LPC channel.
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I9db77f78b0aa4e289fb0ab940121569b431f4dfe
diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp
index 0c7216b..05051b6 100644
--- a/oem/ibm/libpldmresponder/file_io.cpp
+++ b/oem/ibm/libpldmresponder/file_io.cpp
@@ -47,6 +47,8 @@
std::move(writeFileByTypeFromMemory));
registerHandler(PLDM_OEM, PLDM_READ_FILE_BY_TYPE_INTO_MEMORY,
std::move(readFileByTypeIntoMemory));
+ registerHandler(PLDM_OEM, PLDM_READ_FILE_BY_TYPE,
+ std::move(readFileByType));
}
} // namespace oem_ibm
@@ -612,5 +614,52 @@
payloadLength);
}
+Response readFileByType(const pldm_msg* request, size_t payloadLength)
+{
+ Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+
+ if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES)
+ {
+ encode_rw_file_by_type_resp(request->hdr.instance_id,
+ PLDM_READ_FILE_BY_TYPE,
+ PLDM_ERROR_INVALID_LENGTH, 0, responsePtr);
+ return response;
+ }
+ uint16_t fileType{};
+ uint32_t fileHandle{};
+ uint32_t offset{};
+ uint32_t length{};
+
+ auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType,
+ &fileHandle, &offset, &length);
+ if (rc != PLDM_SUCCESS)
+ {
+ encode_rw_file_by_type_resp(request->hdr.instance_id,
+ PLDM_READ_FILE_BY_TYPE, rc, 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_resp(request->hdr.instance_id,
+ PLDM_READ_FILE_BY_TYPE,
+ PLDM_INVALID_FILE_TYPE, 0, responsePtr);
+ return response;
+ }
+
+ rc = handler->read(offset, length, response);
+ encode_rw_file_by_type_resp(request->hdr.instance_id,
+ PLDM_READ_FILE_BY_TYPE, rc, length,
+ responsePtr);
+ return response;
+}
+
} // namespace responder
} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp
index b67f0f9..07a13aa 100644
--- a/oem/ibm/libpldmresponder/file_io.hpp
+++ b/oem/ibm/libpldmresponder/file_io.hpp
@@ -160,6 +160,15 @@
Response readFileByTypeIntoMemory(const pldm_msg* request,
size_t payloadLength);
+/** @brief Handler for readFileByType command
+ *
+ * @param[in] request - pointer to PLDM request payload
+ * @param[in] payloadLength - length of the message
+ *
+ * @return PLDM response message
+ */
+Response readFileByType(const pldm_msg* request, size_t payloadLength);
+
/** @brief Handler for GetFileTable command
*
* @param[in] request - pointer to PLDM request payload
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp
index 152efb9..efe8e37 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.cpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -12,6 +12,7 @@
#include <exception>
#include <filesystem>
+#include <fstream>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <vector>
@@ -29,7 +30,7 @@
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
int FileHandler::transferFileData(const fs::path& path, bool upstream,
- uint32_t offset, uint32_t length,
+ uint32_t offset, uint32_t& length,
uint64_t address)
{
if (upstream)
@@ -103,5 +104,43 @@
return nullptr;
}
+int FileHandler::readFile(const std::string& filePath, uint32_t offset,
+ uint32_t& length, Response& response)
+{
+ if (!fs::exists(filePath))
+ {
+ log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle),
+ entry("PATH=%s", filePath.c_str()));
+ return PLDM_INVALID_FILE_HANDLE;
+ }
+
+ size_t fileSize = fs::file_size(filePath);
+ if (offset >= fileSize)
+ {
+ log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
+ entry("FILE_SIZE=%d", fileSize));
+ return PLDM_DATA_OUT_OF_RANGE;
+ }
+
+ if (offset + length > fileSize)
+ {
+ length = fileSize - offset;
+ }
+
+ size_t currSize = response.size();
+ response.resize(currSize + length);
+ auto filePos = reinterpret_cast<char*>(response.data());
+ filePos += currSize;
+ std::ifstream stream(filePath, std::ios::in | std::ios::binary);
+ if (stream)
+ {
+ stream.seekg(offset);
+ stream.read(filePos, length);
+ return PLDM_SUCCESS;
+ }
+ log<level::ERR>("Unable to read file", entry("FILE=%s", filePath.c_str()));
+ return PLDM_ERROR;
+}
+
} // namespace responder
} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.hpp b/oem/ibm/libpldmresponder/file_io_by_type.hpp
index f39650d..779eaef 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.hpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.hpp
@@ -33,13 +33,31 @@
* file types need to override this method to do the file specific
* processing
* @param[in] offset - offset to read
- * @param[in] length - length to be read mentioned by Host
+ * @param[in/out] length - length to be read mentioned by Host
* @param[in] address - DMA address
* @return PLDM status code
*/
- virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ virtual int readIntoMemory(uint32_t offset, uint32_t& length,
uint64_t address) = 0;
+ /** @brief Method to read an oem file type's content into the PLDM response.
+ * @param[in] offset - offset to read
+ * @param[in/out] length - length to be read
+ * @param[in] response - PLDM response
+ * @return PLDM status code
+ */
+ virtual int read(uint32_t offset, uint32_t& length, Response& response) = 0;
+
+ /** @brief Method to read an oem file type's content into the PLDM response.
+ * @param[in] filePath - file to read from
+ * @param[in] offset - offset to read
+ * @param[in/out] length - length to be read
+ * @param[in] response - PLDM response
+ * @return PLDM status code
+ */
+ virtual int readFile(const std::string& filePath, uint32_t offset,
+ uint32_t& length, Response& response);
+
/** @brief Method to do the file content transfer ove DMA between host and
* bmc. This method is made virtual to be overridden in test case. And need
* not be defined in other child classes
@@ -48,13 +66,13 @@
* @param[in] upstream - direction of DMA transfer. "false" means a
* transfer from host to BMC
* @param[in] offset - offset to read/write
- * @param[in] length - length to be read/write mentioned by Host
+ * @param[in/out] length - length to be read/write mentioned by Host
* @param[in] address - DMA address
*
* @return PLDM status code
*/
virtual int transferFileData(const fs::path& path, bool upstream,
- uint32_t offset, uint32_t length,
+ uint32_t offset, uint32_t& length,
uint64_t address);
/** @brief Constructor to create a FileHandler object
diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
index 45d4f73..d3a48a5 100644
--- a/oem/ibm/libpldmresponder/file_io_type_lid.hpp
+++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
@@ -38,12 +38,17 @@
return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
}
- virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ virtual int readIntoMemory(uint32_t offset, uint32_t& length,
uint64_t address)
{
return transferFileData(lidPath, true, offset, length, address);
}
+ virtual int read(uint32_t offset, uint32_t& length, Response& response)
+ {
+ return readFile(lidPath, offset, length, response);
+ }
+
/** @brief LidHandler destructor
*/
~LidHandler()
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
index 014511c..01919b9 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
@@ -25,12 +25,18 @@
using namespace phosphor::logging;
-int PelHandler::readIntoMemory(uint32_t /*offset*/, uint32_t /*length*/,
+int PelHandler::readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/,
uint64_t /*address*/)
{
return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
}
+int PelHandler::read(uint32_t /*offset*/, uint32_t& /*length*/,
+ Response& /*response*/)
+{
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+}
+
int PelHandler::writeFromMemory(uint32_t offset, uint32_t length,
uint64_t address)
{
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.hpp b/oem/ibm/libpldmresponder/file_io_type_pel.hpp
index 4c79452..d2fb5cc 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.hpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.hpp
@@ -25,8 +25,9 @@
virtual int writeFromMemory(uint32_t offset, uint32_t length,
uint64_t address);
- virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ virtual int readIntoMemory(uint32_t offset, uint32_t& length,
uint64_t address);
+ virtual int read(uint32_t offset, uint32_t& length, Response& response);
/** @brief method to store a pel file in tempfs and send
* d-bus notification to pel daemon that it is ready for consumption