From 44f43f94cebec44c80ca5db6f16de165204cfff2 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 16 Dec 2020 22:11:16 +0100 Subject: [PATCH] OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the functions introduced previously, we can now implement VirtioFsSimpleFileWrite(). Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Philippe Mathieu-Daudé Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3097 Signed-off-by: Laszlo Ersek Message-Id: <20201216211125.19496-40-lersek@redhat.com> Acked-by: Ard Biesheuvel --- OvmfPkg/VirtioFsDxe/SimpleFsWrite.c | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c b/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c index 90d82bd722..8ae317c88e 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c @@ -16,5 +16,66 @@ VirtioFsSimpleFileWrite ( IN VOID *Buffer ) { - return EFI_NO_MEDIA; + 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; }