[Skiboot] [PATCH V6 20/21] core/pldm: Add file io write request
Christophe Lombard
clombard at linux.vnet.ibm.com
Wed Apr 19 00:57:21 AEST 2023
Le 12/04/2023 à 18:37, Frederic Barrat a écrit :
>
>
> On 13/09/2022 12:27, Christophe Lombard wrote:
>> 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 at linux.vnet.ibm.com>
>> ---
>> core/pldm/pldm-file-io-requests.c | 123 ++++++++++++++++++++++++++++++
>> core/pldm/pldm.h | 2 +
>> 2 files changed, 125 insertions(+)
>>
>> diff --git a/core/pldm/pldm-file-io-requests.c
>> b/core/pldm/pldm-file-io-requests.c
>> index 48b00ef2..0665a679 100644
>> --- a/core/pldm/pldm-file-io-requests.c
>> +++ b/core/pldm/pldm-file-io-requests.c
>> @@ -162,6 +162,129 @@ 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)
>> +{
>
>
> Unlike the read API, we don't have the file_size of the lid. Expected?
> Can we "grow" the file? what happens if we go over?
>
We encode a write file request with a specific offset and a length
(data). The BMC will handle writing the file.
It's up to the BMC to manage the 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);
>
>
> zalloc()? (it's actually in the next patch)
> We should check for a failed allocation.
>
Yep.
>
>> +
>> + payload_data = ((struct pldm_msg *)request_msg)->payload
>> + + sizeof(file_req.file_handle)
>> + + sizeof(file_req.offset)
>> + + sizeof(file_req.length);
>
>
> We could use offsetof(struct pldm_write_file_req, file_data)
>
>
correct. Thanks
>> + 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);
>> +
>
>
> I don't understand how it works when num_transfers > 1. Seems like we
> never update the content being sent over.
>
>
During the loop, we update the offset. The request will take into
account of this value.
>> + /* 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_requester_queue_and_wait(
>> + request_msg, request_length - 1,
>> + &response_msg, &response_len);
>> + if (rc) {
>> + prlog(PR_ERR, "Communication Error, req: WriteFileReq,
>> rc: %d\n", rc);
>> + free(request_msg);
>> + return rc;
>> + }
>> +
>> + /* 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);
>> + free(response_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 2b2a979d..688c7996 100644
>> --- a/core/pldm/pldm.h
>> +++ b/core/pldm/pldm.h
>> @@ -49,6 +49,8 @@ int pldm_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_bmc_version(void *bv);
More information about the Skiboot
mailing list