oem-ibm: add readFileByTypeIntoMemory handler
Add a handler for file type 'LID', which are host firmware image files
on IBM systems. These would be read by the host firmware as it boots.
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: I83e3ee398a4c6a4198a40b8b2188a3c11d0e55c4
diff --git a/meson.build b/meson.build
index 13a1899..bca95eb 100644
--- a/meson.build
+++ b/meson.build
@@ -20,6 +20,8 @@
if get_option('oem-ibm').enabled()
conf_data.set_quoted('FILE_TABLE_JSON', '/usr/share/pldm/fileTable.json')
conf_data.set_quoted('PEL_TEMP_DIR', '/tmp/pel')
+ conf_data.set_quoted('LID_PERM_DIR', '/var/lib/pldm/lid')
+ conf_data.set_quoted('LID_TEMP_DIR', '/var/lib/pldm/lid/temp')
add_global_arguments('-DOEM_IBM', language : 'c')
add_global_arguments('-DOEM_IBM', language : 'cpp')
endif
diff --git a/oem/ibm/libpldm/file_io.h b/oem/ibm/libpldm/file_io.h
index c4ab935..8d9a9a3 100644
--- a/oem/ibm/libpldm/file_io.h
+++ b/oem/ibm/libpldm/file_io.h
@@ -48,6 +48,8 @@
*/
enum pldm_fileio_file_type {
PLDM_FILE_TYPE_PEL = 0,
+ PLDM_FILE_TYPE_LID_PERM = 1,
+ PLDM_FILE_TYPE_LID_TEMP = 2,
};
#define PLDM_RW_FILE_MEM_REQ_BYTES 20
diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp
index 692ae1b..0c7216b 100644
--- a/oem/ibm/libpldmresponder/file_io.cpp
+++ b/oem/ibm/libpldmresponder/file_io.cpp
@@ -45,6 +45,8 @@
registerHandler(PLDM_OEM, PLDM_WRITE_FILE, std::move(writeFile));
registerHandler(PLDM_OEM, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
std::move(writeFileByTypeFromMemory));
+ registerHandler(PLDM_OEM, PLDM_READ_FILE_BY_TYPE_INTO_MEMORY,
+ std::move(readFileByTypeIntoMemory));
}
} // namespace oem_ibm
@@ -536,8 +538,8 @@
return response;
}
-Response writeFileByTypeFromMemory(const pldm_msg* request,
- size_t payloadLength)
+Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request,
+ size_t payloadLength)
{
Response response(
sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0);
@@ -545,9 +547,9 @@
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);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
+ PLDM_ERROR_INVALID_LENGTH, 0,
+ responsePtr);
return response;
}
@@ -561,18 +563,17 @@
&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);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0,
+ responsePtr);
return response;
}
if (length % dma::minSize)
{
- log<level::ERR>("Write length is not a multiple of DMA minSize",
+ log<level::ERR>("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);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
+ PLDM_INVALID_WRITE_LENGTH, 0,
+ responsePtr);
return response;
}
@@ -584,18 +585,32 @@
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);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd,
+ 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,
+ rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY
+ ? handler->writeFromMemory(offset, length, address)
+ : handler->readIntoMemory(offset, length, address);
+ encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc,
length, responsePtr);
return response;
}
+Response writeFileByTypeFromMemory(const pldm_msg* request,
+ size_t payloadLength)
+{
+ return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request,
+ payloadLength);
+}
+
+Response readFileByTypeIntoMemory(const pldm_msg* request, size_t payloadLength)
+{
+ return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request,
+ payloadLength);
+}
+
} // namespace responder
} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp
index 2086fc1..b67f0f9 100644
--- a/oem/ibm/libpldmresponder/file_io.hpp
+++ b/oem/ibm/libpldmresponder/file_io.hpp
@@ -150,6 +150,16 @@
Response writeFileByTypeFromMemory(const pldm_msg* request,
size_t payloadLength);
+/** @brief Handler for readFileByTypeIntoMemory command
+ *
+ * @param[in] request - pointer to PLDM request payload
+ * @param[in] payloadLength - length of the message
+ *
+ * @return PLDM response message
+ */
+Response readFileByTypeIntoMemory(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 d8a40a5..152efb9 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.cpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -2,6 +2,7 @@
#include "file_io_by_type.hpp"
+#include "file_io_type_lid.hpp"
#include "file_io_type_pel.hpp"
#include "libpldmresponder/utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
@@ -31,6 +32,29 @@
uint32_t offset, uint32_t length,
uint64_t address)
{
+ if (upstream)
+ {
+ if (!fs::exists(path))
+ {
+ log<level::ERR>("File does not exist",
+ entry("PATH=%s", path.c_str()));
+ return PLDM_INVALID_FILE_HANDLE;
+ }
+
+ size_t fileSize = fs::file_size(path);
+ 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;
+ }
+ }
+
dma::DMA xdmaInterface;
while (length > dma::maxSize)
@@ -60,6 +84,16 @@
return std::make_unique<PelHandler>(fileHandle);
break;
}
+ case PLDM_FILE_TYPE_LID_PERM:
+ {
+ return std::make_unique<LidHandler>(fileHandle, true);
+ break;
+ }
+ case PLDM_FILE_TYPE_LID_TEMP:
+ {
+ return std::make_unique<LidHandler>(fileHandle, false);
+ break;
+ }
default:
{
elog<InternalFailure>();
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.hpp b/oem/ibm/libpldmresponder/file_io_by_type.hpp
index 6c31252..f39650d 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.hpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.hpp
@@ -29,6 +29,17 @@
virtual int writeFromMemory(uint32_t offset, uint32_t length,
uint64_t address) = 0;
+ /** @brief Method to read an oem file type into host memory. Individual
+ * 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] address - DMA address
+ * @return PLDM status code
+ */
+ virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ uint64_t address) = 0;
+
/** @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
diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
new file mode 100644
index 0000000..45d4f73
--- /dev/null
+++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "config.h"
+
+#include "file_io_by_type.hpp"
+
+#include <sstream>
+#include <string>
+
+namespace pldm
+{
+namespace responder
+{
+
+using namespace pldm::responder::dma;
+
+/** @class LidHandler
+ *
+ * @brief Inherits and implements FileHandler. This class is used
+ * to read/write LIDs.
+ */
+class LidHandler : public FileHandler
+{
+ public:
+ /** @brief LidHandler constructor
+ */
+ LidHandler(uint32_t fileHandle, bool permSide) : FileHandler(fileHandle)
+ {
+ std::string dir = permSide ? LID_PERM_DIR : LID_TEMP_DIR;
+ std::stringstream stream;
+ stream << std::hex << fileHandle;
+ lidPath = std::move(dir) + '/' + stream.str() + ".lid";
+ }
+
+ virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/,
+ uint64_t /*address*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+
+ virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ uint64_t address)
+ {
+ return transferFileData(lidPath, true, offset, length, address);
+ }
+
+ /** @brief LidHandler destructor
+ */
+ ~LidHandler()
+ {
+ }
+
+ protected:
+ std::string lidPath;
+};
+
+} // namespace responder
+} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
index 400d336..014511c 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
@@ -25,6 +25,12 @@
using namespace phosphor::logging;
+int PelHandler::readIntoMemory(uint32_t /*offset*/, uint32_t /*length*/,
+ uint64_t /*address*/)
+{
+ 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 92bcbf6..4c79452 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.hpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.hpp
@@ -25,6 +25,8 @@
virtual int writeFromMemory(uint32_t offset, uint32_t length,
uint64_t address);
+ virtual int readIntoMemory(uint32_t offset, uint32_t length,
+ uint64_t address);
/** @brief method to store a pel file in tempfs and send
* d-bus notification to pel daemon that it is ready for consumption