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