oem-ibm: libpldm: add file IO APIs
This commit implements encode and decode APIs for in-band readFile and
writeFile commands.
In-band file IO is preferred over DMA for smaller files.
Change-Id: I92ec011560ba39aed497f533074479236abeb766
Signed-off-by: vkaverap <vkaverap@in.ibm.com>
diff --git a/oem/ibm/libpldm/file_io.c b/oem/ibm/libpldm/file_io.c
index 7806ae6..dc8ad6b 100644
--- a/oem/ibm/libpldm/file_io.c
+++ b/oem/ibm/libpldm/file_io.c
@@ -155,3 +155,229 @@
return PLDM_SUCCESS;
}
+
+int decode_read_file_req(const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *file_handle, uint32_t *offset,
+ uint32_t *length)
+{
+ if (msg == NULL || file_handle == NULL || offset == NULL ||
+ length == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length != PLDM_READ_FILE_REQ_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_read_file_req *request =
+ (struct pldm_read_file_req *)msg->payload;
+
+ *file_handle = le32toh(request->file_handle);
+ *offset = le32toh(request->offset);
+ *length = le32toh(request->length);
+
+ return PLDM_SUCCESS;
+}
+
+int encode_read_file_req(uint8_t instance_id, uint32_t file_handle,
+ uint32_t offset, uint32_t length, struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_REQUEST;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_OEM;
+ header.command = PLDM_READ_FILE;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (length == 0) {
+ return PLDM_INVALID_READ_LENGTH;
+ }
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_read_file_req *request =
+ (struct pldm_read_file_req *)msg->payload;
+
+ request->file_handle = htole32(file_handle);
+ request->offset = htole32(offset);
+ request->length = htole32(length);
+
+ return PLDM_SUCCESS;
+}
+
+int decode_read_file_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *length,
+ size_t *file_data_offset)
+{
+ if (msg == NULL || completion_code == NULL || length == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length < PLDM_READ_FILE_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_read_file_resp *response =
+ (struct pldm_read_file_resp *)msg->payload;
+
+ *completion_code = response->completion_code;
+ if (*completion_code == PLDM_SUCCESS) {
+ *length = le32toh(response->length);
+ if (payload_length != PLDM_READ_FILE_RESP_BYTES + *length) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ *file_data_offset = sizeof(*completion_code) + sizeof(*length);
+ }
+
+ return PLDM_SUCCESS;
+}
+
+int encode_read_file_resp(uint8_t instance_id, uint8_t completion_code,
+ uint32_t length, struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_RESPONSE;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_OEM;
+ header.command = PLDM_READ_FILE;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_read_file_resp *response =
+ (struct pldm_read_file_resp *)msg->payload;
+ response->completion_code = completion_code;
+
+ if (response->completion_code == PLDM_SUCCESS) {
+ response->length = htole32(length);
+ }
+
+ return PLDM_SUCCESS;
+}
+
+int decode_write_file_req(const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *file_handle, uint32_t *offset,
+ uint32_t *length, size_t *file_data_offset)
+{
+ if (msg == NULL || file_handle == NULL || length == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length < PLDM_WRITE_FILE_REQ_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_write_file_req *request =
+ (struct pldm_write_file_req *)msg->payload;
+
+ *file_handle = le32toh(request->file_handle);
+ *offset = le32toh(request->offset);
+ *length = le32toh(request->length);
+ if (payload_length != PLDM_WRITE_FILE_REQ_BYTES + *length) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ *file_data_offset =
+ sizeof(*file_handle) + sizeof(*offset) + sizeof(*length);
+
+ return PLDM_SUCCESS;
+}
+
+int encode_write_file_req(uint8_t instance_id, uint32_t file_handle,
+ uint32_t offset, uint32_t length,
+ struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_REQUEST;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_OEM;
+ header.command = PLDM_WRITE_FILE;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ if (length == 0) {
+ return PLDM_INVALID_WRITE_LENGTH;
+ }
+
+ struct pldm_write_file_req *request =
+ (struct pldm_write_file_req *)msg->payload;
+
+ request->file_handle = htole32(file_handle);
+ request->offset = htole32(offset);
+ request->length = htole32(length);
+
+ return PLDM_SUCCESS;
+}
+
+int decode_write_file_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *length)
+{
+ if (msg == NULL || completion_code == NULL || length == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length != PLDM_WRITE_FILE_RESP_BYTES) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_write_file_resp *response =
+ (struct pldm_write_file_resp *)msg->payload;
+
+ *completion_code = le32toh(response->completion_code);
+ if (response->completion_code == PLDM_SUCCESS) {
+ *length = le32toh(response->length);
+ }
+
+ return PLDM_SUCCESS;
+}
+
+int encode_write_file_resp(uint8_t instance_id, uint8_t completion_code,
+ uint32_t length, struct pldm_msg *msg)
+{
+ struct pldm_header_info header = {0};
+ int rc = PLDM_SUCCESS;
+
+ header.msg_type = PLDM_RESPONSE;
+ header.instance = instance_id;
+ header.pldm_type = PLDM_OEM;
+ header.command = PLDM_WRITE_FILE;
+
+ if (msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if ((rc = pack_pldm_header(&header, &(msg->hdr))) > PLDM_SUCCESS) {
+ return rc;
+ }
+
+ struct pldm_write_file_resp *response =
+ (struct pldm_write_file_resp *)msg->payload;
+ response->completion_code = completion_code;
+
+ if (response->completion_code == PLDM_SUCCESS) {
+ response->length = htole32(length);
+ }
+
+ return PLDM_SUCCESS;
+}
diff --git a/oem/ibm/libpldm/file_io.h b/oem/ibm/libpldm/file_io.h
index b3a0f73..437897c 100644
--- a/oem/ibm/libpldm/file_io.h
+++ b/oem/ibm/libpldm/file_io.h
@@ -14,6 +14,8 @@
*/
enum pldm_fileio_commands {
PLDM_GET_FILE_TABLE = 0x1,
+ PLDM_READ_FILE = 0x4,
+ PLDM_WRITE_FILE = 0x5,
PLDM_READ_FILE_INTO_MEMORY = 0x6,
PLDM_WRITE_FILE_FROM_MEMORY = 0x7,
};
@@ -40,6 +42,10 @@
#define PLDM_RW_FILE_MEM_RESP_BYTES 5
#define PLDM_GET_FILE_TABLE_REQ_BYTES 6
#define PLDM_GET_FILE_TABLE_MIN_RESP_BYTES 6
+#define PLDM_READ_FILE_REQ_BYTES 12
+#define PLDM_READ_FILE_RESP_BYTES 5
+#define PLDM_WRITE_FILE_REQ_BYTES 12
+#define PLDM_WRITE_FILE_RESP_BYTES 5
/** @struct pldm_read_write_file_memory_req
*
@@ -178,6 +184,163 @@
uint8_t transfer_flag, const uint8_t *table_data,
size_t table_size, struct pldm_msg *msg);
+/** @struct pldm_read_file_req
+ *
+ * Structure representing ReadFile request
+ */
+struct pldm_read_file_req {
+ uint32_t file_handle; //!< Handle to file
+ uint32_t offset; //!< Offset to file where read starts
+ uint32_t length; //!< Bytes to be read
+} __attribute__((packed));
+
+/** @struct pldm_read_file_resp
+ *
+ * Structure representing ReadFile response data
+ */
+struct pldm_read_file_resp {
+ uint8_t completion_code; //!< Completion code
+ uint32_t length; //!< Number of bytes read
+ uint8_t file_data[1]; //!< Address of this is where file data starts
+} __attribute__((packed));
+
+/** @struct pldm_write_file_req
+ *
+ * Structure representing WriteFile request
+ */
+struct pldm_write_file_req {
+ uint32_t file_handle; //!< Handle to file
+ uint32_t offset; //!< Offset to file where write starts
+ uint32_t length; //!< Bytes to be written
+ uint8_t file_data[1]; //!< Address of this is where file data starts
+} __attribute__((packed));
+
+/** @struct pldm_write_file_resp
+ *
+ * Structure representing WriteFile response data
+ */
+struct pldm_write_file_resp {
+ uint8_t completion_code; //!< Completion code
+ uint32_t length; //!< Bytes written
+} __attribute__((packed));
+
+/** @brief Decode Read File commands request
+ *
+ * @param[in] msg - PLDM request message payload
+ * @param[in] payload_length - Length of request payload
+ * @param[out] file_handle - A handle to the file
+ * @param[out] offset - Offset to the file at which the read should begin
+ * @param[out] length - Number of bytes read
+ * @return pldm_completion_codes
+ */
+int decode_read_file_req(const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *file_handle, uint32_t *offset,
+ uint32_t *length);
+
+/** @brief Encode Read File commands request
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] file_handle - A handle to the file
+ * @param[in] offset - Offset to the file at which the read should begin
+ * @param[in] length - Number of bytes read
+ * @param[in,out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param 'msg'
+ */
+int encode_read_file_req(uint8_t instance_id, uint32_t file_handle,
+ uint32_t offset, uint32_t length,
+ struct pldm_msg *msg);
+
+/** @brief Decode Read File commands response
+ *
+ * @param[in] msg - PLDM response message payload
+ * @param[in] payload_length - Length of request payload
+ * @param[out] completion_code - PLDM completion code
+ * @param[out] length - Number of bytes read. This could be less than what the
+ * requester asked for.
+ * @param[out] file_data_offset - Offset where file data should be read in pldm
+ * msg.
+ * @return pldm_completion_codes
+ */
+int decode_read_file_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *length,
+ size_t *file_data_offset);
+
+/** @brief Create a PLDM response for Read File
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] completion_code - PLDM completion code
+ * @param[in] length - Number of bytes read. This could be less than what the
+ * requester asked for.
+ * @param[in,out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param 'msg'.
+ * Although read file command response includes file data, this function
+ * does not encode the file data to prevent additional copying of the data.
+ * The position of file data is calculated by caller from address and size
+ * of other input arguments.
+ */
+int encode_read_file_resp(uint8_t instance_id, uint8_t completion_code,
+ uint32_t length, struct pldm_msg *msg);
+
+/** @brief Decode Write File commands request
+ *
+ * @param[in] msg - PLDM request message payload
+ * @param[in] payload_length - Length of request payload
+ * @param[out] file_handle - A handle to the file
+ * @param[out] offset - Offset to the file at which the write should begin
+ * @param[out] length - Number of bytes to write
+ * @param[out] file_data_offset - Offset where file data write begins in pldm
+ * msg.
+ * @return pldm_completion_codes
+ */
+int decode_write_file_req(const struct pldm_msg *msg, size_t payload_length,
+ uint32_t *file_handle, uint32_t *offset,
+ uint32_t *length, size_t *file_data_offset);
+
+/** @brief Create a PLDM request for Write File
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] file_handle - A handle to the file
+ * @param[in] offset - Offset to the file at which the read should begin
+ * @param[in] length - Number of bytes written. This could be less than what
+ * the requester asked for.
+ * @param[in,out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param 'msg'.
+ * Although write file command request includes file data, this function
+ * does not encode the file data to prevent additional copying of the data.
+ * The position of file data is calculated by caller from address and size
+ * of other input arguments.
+ */
+int encode_write_file_req(uint8_t instance_id, uint32_t file_handle,
+ uint32_t offset, uint32_t length,
+ struct pldm_msg *msg);
+
+/** @brief Decode Write File commands response
+ *
+ * @param[in] msg - PLDM request message payload
+ * @param[in] payload_length - Length of request payload
+ * @param[out] completion_code - PLDM completion code
+ * @param[out] length - Number of bytes written
+ * @return pldm_completion_codes
+ */
+int decode_write_file_resp(const struct pldm_msg *msg, size_t payload_length,
+ uint8_t *completion_code, uint32_t *length);
+
+/** @brief Create a PLDM response for Write File
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] completion_code - PLDM completion code
+ * @param[in] length - Number of bytes written. This could be less than what
+ * the requester asked for.
+ * @param[in,out] msg - Message will be written to this
+ * @return pldm_completion_codes
+ * @note Caller is responsible for memory alloc and dealloc of param 'msg'
+ */
+int encode_write_file_resp(uint8_t instance_id, uint8_t completion_code,
+ uint32_t length, struct pldm_msg *msg);
+
#ifdef __cplusplus
}
#endif
diff --git a/oem/ibm/test/libpldm_fileio_test.cpp b/oem/ibm/test/libpldm_fileio_test.cpp
index de766b1..665ceb1 100644
--- a/oem/ibm/test/libpldm_fileio_test.cpp
+++ b/oem/ibm/test/libpldm_fileio_test.cpp
@@ -350,3 +350,356 @@
ASSERT_EQ(response->hdr.command, PLDM_GET_FILE_TABLE);
ASSERT_EQ(response->payload[0], PLDM_ERROR);
}
+
+TEST(ReadFile, testGoodDecodeRequest)
+{
+ std::array<uint8_t, PLDM_READ_FILE_REQ_BYTES + sizeof(pldm_msg_hdr)>
+ requestMsg{};
+
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
+ auto request = reinterpret_cast<pldm_read_file_req*>(requestPtr->payload);
+
+ // Random value for fileHandle, offset and length
+ uint32_t fileHandle = 0x12345678;
+ uint32_t offset = 0x87654321;
+ uint32_t length = 0x13245768;
+
+ request->file_handle = fileHandle;
+ request->offset = offset;
+ request->length = length;
+
+ uint32_t retFileHandle = 0;
+ uint32_t retOffset = 0;
+ uint32_t retLength = 0;
+
+ // Invoke decode the read file request
+ auto rc = decode_read_file_req(requestPtr, payload_length, &retFileHandle,
+ &retOffset, &retLength);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(fileHandle, retFileHandle);
+ ASSERT_EQ(offset, retOffset);
+ ASSERT_EQ(length, retLength);
+}
+
+TEST(WriteFile, testGoodDecodeRequest)
+{
+ // Random value for fileHandle, offset, length and file data
+ uint32_t fileHandle = 0x12345678;
+ uint32_t offset = 0x87654321;
+ uint32_t length = 0x467;
+
+ std::vector<uint8_t> requestMsg(PLDM_WRITE_FILE_REQ_BYTES +
+ sizeof(pldm_msg_hdr) + length);
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ size_t payload_length = requestMsg.size() - sizeof(pldm_msg_hdr);
+ auto request = reinterpret_cast<pldm_write_file_req*>(requestPtr->payload);
+
+ size_t fileDataOffset =
+ sizeof(fileHandle) + sizeof(offset) + sizeof(length);
+
+ request->file_handle = fileHandle;
+ request->offset = offset;
+ request->length = length;
+
+ uint32_t retFileHandle = 0;
+ uint32_t retOffset = 0;
+ uint32_t retLength = 0;
+ size_t retFileDataOffset = 0;
+
+ // Invoke decode the write file request
+ auto rc = decode_write_file_req(requestPtr, payload_length, &retFileHandle,
+ &retOffset, &retLength, &retFileDataOffset);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(fileHandle, retFileHandle);
+ ASSERT_EQ(offset, retOffset);
+ ASSERT_EQ(length, retLength);
+ ASSERT_EQ(fileDataOffset, retFileDataOffset);
+}
+
+TEST(ReadFile, testGoodDecodeResponse)
+{
+ // Random value for length
+ uint32_t length = 0x10;
+ uint8_t completionCode = PLDM_SUCCESS;
+
+ std::vector<uint8_t> responseMsg(PLDM_READ_FILE_RESP_BYTES +
+ sizeof(pldm_msg_hdr) + length);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+ auto response =
+ reinterpret_cast<pldm_read_file_resp*>(responsePtr->payload);
+
+ response->completion_code = completionCode;
+ response->length = length;
+
+ size_t fileDataOffset = sizeof(completionCode) + sizeof(length);
+
+ uint32_t retLength = 0;
+ uint8_t retCompletionCode = 0;
+ size_t retFileDataOffset = 0;
+
+ // Invoke decode the read file response
+ auto rc =
+ decode_read_file_resp(responsePtr, payload_length, &retCompletionCode,
+ &retLength, &retFileDataOffset);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(completionCode, retCompletionCode);
+ ASSERT_EQ(length, retLength);
+ ASSERT_EQ(fileDataOffset, retFileDataOffset);
+}
+
+TEST(WriteFile, testGoodDecodeResponse)
+{
+ std::array<uint8_t, PLDM_WRITE_FILE_RESP_BYTES + sizeof(pldm_msg_hdr)>
+ responseMsg{};
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ size_t payload_length = responseMsg.size() - sizeof(pldm_msg_hdr);
+ auto response =
+ reinterpret_cast<pldm_write_file_resp*>(responsePtr->payload);
+
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint32_t length = 0x4678;
+
+ response->completion_code = completionCode;
+ response->length = length;
+
+ uint32_t retLength = 0;
+ uint8_t retCompletionCode = 0;
+
+ // Invoke decode the write file response
+ auto rc = decode_write_file_resp(responsePtr, payload_length,
+ &retCompletionCode, &retLength);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(completionCode, retCompletionCode);
+ ASSERT_EQ(length, retLength);
+}
+
+TEST(ReadWriteFile, testBadDecodeResponse)
+{
+ uint32_t length = 0;
+ uint8_t completionCode = 0;
+ size_t fileDataOffset = 0;
+
+ // Bad decode response for read file
+ std::vector<uint8_t> responseMsg(PLDM_READ_FILE_RESP_BYTES +
+ sizeof(pldm_msg_hdr) + length);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ // Request payload message is missing
+ auto rc = decode_read_file_resp(NULL, 0, &completionCode, &length,
+ &fileDataOffset);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Payload length is invalid
+ rc = decode_read_file_resp(responsePtr, 0, &completionCode, &length,
+ &fileDataOffset);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ // Bad decode response for write file
+ std::array<uint8_t, PLDM_WRITE_FILE_RESP_BYTES + sizeof(pldm_msg_hdr)>
+ responseMsgWr{};
+ auto responseWr = reinterpret_cast<pldm_msg*>(responseMsgWr.data());
+
+ // Request payload message is missing
+ rc = decode_write_file_resp(NULL, 0, &completionCode, &length);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Payload length is invalid
+ rc = decode_write_file_resp(responseWr, 0, &completionCode, &length);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(ReadWriteFile, testBadDecodeRequest)
+{
+ uint32_t fileHandle = 0;
+ uint32_t offset = 0;
+ uint32_t length = 0;
+
+ // Bad decode request for read file
+ std::array<uint8_t, PLDM_READ_FILE_REQ_BYTES + sizeof(pldm_msg_hdr)>
+ requestMsg{};
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ // Request payload message is missing
+ auto rc = decode_read_file_req(NULL, 0, &fileHandle, &offset, &length);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Payload length is invalid
+ rc = decode_read_file_req(requestPtr, 0, &fileHandle, &offset, &length);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ // Bad decode request for write file
+ size_t fileDataOffset = 0;
+ std::array<uint8_t, PLDM_WRITE_FILE_REQ_BYTES> requestMsgWr{};
+ auto requestWr = reinterpret_cast<pldm_msg*>(requestMsgWr.data());
+
+ // Request payload message is missing
+ rc = decode_write_file_req(NULL, 0, &fileHandle, &offset, &length,
+ &fileDataOffset);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ // Payload length is invalid
+ rc = decode_write_file_req(requestWr, 0, &fileHandle, &offset, &length,
+ &fileDataOffset);
+ ASSERT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(ReadFile, testGoodEncodeResponse)
+{
+ // Good encode response for read file
+ uint32_t length = 0x4;
+
+ std::vector<uint8_t> responseMsg(PLDM_READ_FILE_RESP_BYTES +
+ sizeof(pldm_msg_hdr) + length);
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ auto response =
+ reinterpret_cast<pldm_read_file_resp*>(responsePtr->payload);
+
+ // ReadFile
+ auto rc = encode_read_file_resp(0, PLDM_SUCCESS, length, responsePtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_READ_FILE);
+ ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(response->length, length);
+}
+
+TEST(WriteFile, testGoodEncodeResponse)
+{
+ uint32_t length = 0x467;
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES>
+ responseMsg{};
+
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+ auto response =
+ reinterpret_cast<pldm_write_file_resp*>(responsePtr->payload);
+
+ // WriteFile
+ auto rc = encode_write_file_resp(0, PLDM_SUCCESS, length, responsePtr);
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_WRITE_FILE);
+ ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+ ASSERT_EQ(response->length, length);
+}
+
+TEST(ReadFile, testGoodEncodeRequest)
+{
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
+ requestMsg{};
+
+ uint32_t fileHandle = 0x12345678;
+ uint32_t offset = 0x87654321;
+ uint32_t length = 0x13245768;
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto request = reinterpret_cast<pldm_read_file_req*>(requestPtr->payload);
+
+ // ReadFile
+ auto rc = encode_read_file_req(0, fileHandle, offset, length, requestPtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
+ ASSERT_EQ(requestPtr->hdr.instance_id, 0);
+ ASSERT_EQ(requestPtr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(requestPtr->hdr.command, PLDM_READ_FILE);
+ ASSERT_EQ(request->file_handle, fileHandle);
+ ASSERT_EQ(request->offset, offset);
+ ASSERT_EQ(request->length, length);
+}
+
+TEST(WriteFile, testGoodEncodeRequest)
+{
+ uint32_t fileHandle = 0x12345678;
+ uint32_t offset = 0x87654321;
+ uint32_t length = 0x456;
+
+ std::vector<uint8_t> requestMsg(PLDM_WRITE_FILE_REQ_BYTES +
+ sizeof(pldm_msg_hdr) + length);
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ auto request = reinterpret_cast<pldm_write_file_req*>(requestPtr->payload);
+
+ // WriteFile
+ auto rc = encode_write_file_req(0, fileHandle, offset, length, requestPtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
+ ASSERT_EQ(requestPtr->hdr.instance_id, 0);
+ ASSERT_EQ(requestPtr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(requestPtr->hdr.command, PLDM_WRITE_FILE);
+ ASSERT_EQ(request->file_handle, fileHandle);
+ ASSERT_EQ(request->offset, offset);
+ ASSERT_EQ(request->length, length);
+}
+
+TEST(ReadWriteFile, testBadEncodeRequest)
+{
+ // Bad encode request for read file
+ uint32_t fileHandle = 0;
+ uint32_t offset = 0;
+ uint32_t length = 0;
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_REQ_BYTES>
+ requestMsg{};
+ auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ // ReadFile check invalid file length
+ auto rc = encode_read_file_req(0, fileHandle, offset, length, requestPtr);
+
+ ASSERT_EQ(rc, PLDM_INVALID_READ_LENGTH);
+
+ // Bad encode request for write file
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_REQ_BYTES>
+ requestMsgWr{};
+ auto requestWr = reinterpret_cast<pldm_msg*>(requestMsgWr.data());
+
+ // WriteFile check for invalid file length
+ rc = encode_write_file_req(0, fileHandle, offset, length, requestWr);
+
+ ASSERT_EQ(rc, PLDM_INVALID_WRITE_LENGTH);
+}
+
+TEST(ReadWriteFile, testBadEncodeResponse)
+{
+ // Bad encode response for read file
+ uint32_t length = 0;
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES>
+ responseMsg{};
+ auto responsePtr = reinterpret_cast<pldm_msg*>(responseMsg.data());
+
+ // ReadFile
+ auto rc = encode_read_file_resp(0, PLDM_ERROR, length, responsePtr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responsePtr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responsePtr->hdr.instance_id, 0);
+ ASSERT_EQ(responsePtr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(responsePtr->hdr.command, PLDM_READ_FILE);
+ ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR);
+
+ // Bad encode response for write file
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES>
+ responseMsgWr{};
+ auto responseWr = reinterpret_cast<pldm_msg*>(responseMsgWr.data());
+
+ // WriteFile
+ rc = encode_write_file_resp(0, PLDM_ERROR, length, responseWr);
+
+ ASSERT_EQ(rc, PLDM_SUCCESS);
+ ASSERT_EQ(responseWr->hdr.request, PLDM_RESPONSE);
+ ASSERT_EQ(responseWr->hdr.instance_id, 0);
+ ASSERT_EQ(responseWr->hdr.type, PLDM_OEM);
+ ASSERT_EQ(responseWr->hdr.command, PLDM_WRITE_FILE);
+ ASSERT_EQ(responseWr->payload[0], PLDM_ERROR);
+}