/** @file | |
EFI_FILE_PROTOCOL.Write() member function for the Virtio Filesystem driver. | |
Copyright (C) 2020, Red Hat, Inc. | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "VirtioFsDxe.h" | |
EFI_STATUS | |
EFIAPI | |
VirtioFsSimpleFileWrite ( | |
IN EFI_FILE_PROTOCOL *This, | |
IN OUT UINTN *BufferSize, | |
IN VOID *Buffer | |
) | |
{ | |
VIRTIO_FS_FILE *VirtioFsFile; | |
VIRTIO_FS *VirtioFs; | |
EFI_STATUS Status; | |
UINTN Transferred; | |
UINTN Left; | |
VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This); | |
VirtioFs = VirtioFsFile->OwnerFs; | |
if (VirtioFsFile->IsDirectory) { | |
return EFI_UNSUPPORTED; | |
} | |
if (!VirtioFsFile->IsOpenForWriting) { | |
return EFI_ACCESS_DENIED; | |
} | |
Status = EFI_SUCCESS; | |
Transferred = 0; | |
Left = *BufferSize; | |
while (Left > 0) { | |
UINT32 WriteSize; | |
// | |
// Honor the write buffer size limit. | |
// | |
WriteSize = (UINT32)MIN ((UINTN)VirtioFs->MaxWrite, Left); | |
Status = VirtioFsFuseWrite ( | |
VirtioFs, | |
VirtioFsFile->NodeId, | |
VirtioFsFile->FuseHandle, | |
VirtioFsFile->FilePosition + Transferred, | |
&WriteSize, | |
(UINT8 *)Buffer + Transferred | |
); | |
if (!EFI_ERROR (Status) && (WriteSize == 0)) { | |
// | |
// Progress should have been made. | |
// | |
Status = EFI_DEVICE_ERROR; | |
} | |
if (EFI_ERROR (Status)) { | |
break; | |
} | |
Transferred += WriteSize; | |
Left -= WriteSize; | |
} | |
*BufferSize = Transferred; | |
VirtioFsFile->FilePosition += Transferred; | |
// | |
// According to the UEFI spec, | |
// | |
// - 'Partial writes only occur when there has been a data error during the | |
// write attempt (such as "file space full")', and | |
// | |
// - (as an example) EFI_VOLUME_FULL is returned when 'The volume is full'. | |
// | |
// These together imply that after a partial write, we have to return an | |
// error. In other words, (Transferred > 0) is inconsequential for the return | |
// value. | |
// | |
return Status; | |
} |