diff mbox series

[V3,20/21] core/pldm: Add file io write request

Message ID 20220318143619.83489-21-clombard@linux.vnet.ibm.com
State Superseded
Headers show
Series Implement MCTP and PLDM features | expand

Commit Message

Christophe Lombard March 18, 2022, 2:36 p.m. UTC
Send/receive a PLDM WriteFile request message.

Due to maximum transfer size for PLDM protocol, we have to send several
write requests, if necessary.

Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
---
 core/pldm/pldm-file-io-requests.c | 124 ++++++++++++++++++++++++++++++
 core/pldm/pldm.h                  |   2 +
 2 files changed, 126 insertions(+)
diff mbox series

Patch

diff --git a/core/pldm/pldm-file-io-requests.c b/core/pldm/pldm-file-io-requests.c
index a265c6d9..8212a219 100644
--- a/core/pldm/pldm-file-io-requests.c
+++ b/core/pldm/pldm-file-io-requests.c
@@ -160,6 +160,130 @@  int pldm_file_io_read_file(uint32_t file_handle, uint32_t file_length,
 	return read_file_req(file_handle, file_length, buf, offset, size);
 }
 
+/*
+ * Send/receive a PLDM WriteFile request message.
+ */
+static int write_file_req(uint32_t file_handle, const void *buf,
+			  uint32_t offset, uint64_t size)
+{
+	void *response_msg, *current_ptr, *payload_data;
+	uint32_t total_write, resp_length, request_length;
+	size_t response_len, payload_len;
+	uint8_t completion_code;
+	int num_transfers;
+	char *request_msg;
+	int rc, i;
+
+	struct pldm_write_file_req file_req = {
+		.file_handle = file_handle,
+		.offset = offset,
+		.length = size
+	};
+
+	if (!size)
+		return OPAL_PARAMETER;
+
+	if ((offset) && (offset > size))
+		return OPAL_PARAMETER;
+
+	request_length = sizeof(struct pldm_msg_hdr) +
+			 sizeof(struct pldm_write_file_req) +
+			 size;
+	request_msg = malloc(request_length);
+
+	payload_data = ((struct pldm_msg *)request_msg)->payload
+			+ sizeof(file_req.file_handle)
+			+ sizeof(file_req.offset)
+			+ sizeof(file_req.length);
+	memcpy(payload_data, buf, size);
+	current_ptr = payload_data;
+	num_transfers = 1;
+	total_write = 0;
+
+	if (size > MAX_TRANSFER_SIZE_BYTES) {
+		num_transfers = (size + MAX_TRANSFER_SIZE_BYTES - 1) /
+				MAX_TRANSFER_SIZE_BYTES;
+		file_req.length = MAX_TRANSFER_SIZE_BYTES;
+	}
+
+	prlog(PR_TRACE, "%s - file_handle: %d, offset: 0x%x, size: 0x%x, num_transfers: %d\n",
+			__func__, file_handle, file_req.offset,
+			file_req.length, num_transfers);
+
+	for (i = 0; i < num_transfers; i++) {
+		file_req.offset = offset + (i * MAX_TRANSFER_SIZE_BYTES);
+
+		/* Encode the file request */
+		rc = encode_write_file_req(
+				DEFAULT_INSTANCE_ID,
+				file_req.file_handle,
+				file_req.offset,
+				file_req.length,
+				(struct pldm_msg *)request_msg);
+		if (rc != PLDM_SUCCESS) {
+			prlog(PR_ERR, "Encode WriteFileReq Error (rc: %d)\n",
+				      rc);
+			free(request_msg);
+			return OPAL_PARAMETER;
+		}
+
+		/* Send and get the response message bytes */
+		rc = pldm_do_request(BMC_EID, request_msg,
+				     request_length - 1,
+				     &response_msg, &response_len);
+		if (rc) {
+			prlog(PR_ERR, "PLDM: Communication Error (req:"
+				      "WriteFileReq, rc: %d)\n", rc);
+			free(request_msg);
+			return OPAL_PARAMETER;
+		}
+
+		/* Decode the message */
+		payload_len = response_len - sizeof(struct pldm_msg_hdr);
+		rc = decode_write_file_resp(
+				response_msg,
+				payload_len,
+				&completion_code,
+				&resp_length);
+		if (rc != PLDM_SUCCESS || completion_code != PLDM_SUCCESS) {
+			prlog(PR_ERR, "Decode WriteFileResp Error (rc: %d, cc: %d)\n",
+				      rc, completion_code);
+			free(request_msg);
+			return OPAL_PARAMETER;
+		}
+
+		if (resp_length == 0) {
+			free(response_msg);
+			break;
+		}
+
+		total_write += resp_length;
+		current_ptr += resp_length;
+		free(response_msg);
+
+		if (total_write == size)
+			break;
+		else if (resp_length != file_req.length) {
+			/* end of file */
+			break;
+		} else if (MAX_TRANSFER_SIZE_BYTES > (size - total_write))
+			file_req.length = size - total_write;
+	}
+
+	free(request_msg);
+
+	return OPAL_SUCCESS;
+}
+
+int pldm_file_io_write_file(uint32_t file_handle, const void *buf,
+			    uint32_t offset, uint64_t size)
+{
+	if (!file_io_ready)
+		return OPAL_PARAMETER;
+
+	return write_file_req(file_handle, buf, offset, size);
+}
+
 /*
  * Send/receive a PLDM GetFileTable request message.
  * The file table contains the list of files available and
diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
index 617fe3d5..ebacde56 100644
--- a/core/pldm/pldm.h
+++ b/core/pldm/pldm.h
@@ -51,6 +51,8 @@  int pldm_mctp_responder_init(void);
 /* Requester support */
 int pldm_file_io_read_file(uint32_t file_handle, uint32_t file_length,
 			   void *buf, uint32_t offset, uint64_t size);
+int pldm_file_io_write_file(uint32_t file_handle, const void *buf,
+			    uint32_t offset, uint64_t size);
 int pldm_file_io_init(void);
 
 int pldm_fru_get_record_by_option(uint16_t fru_table_handle,