From: Laszlo Ersek Date: Wed, 16 Dec 2020 21:11:10 +0000 (+0100) Subject: OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Read() for regular files X-Git-Tag: edk2-stable202102~283 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=1c05df69984d3f515be991863f69c379e7dc9cba OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Read() for regular files Using the functions introduced previously, we can now implement VirtioFsSimpleFileRead(); for regular files at first. 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-34-lersek@redhat.com> Acked-by: Ard Biesheuvel --- diff --git a/OvmfPkg/VirtioFsDxe/SimpleFsRead.c b/OvmfPkg/VirtioFsDxe/SimpleFsRead.c index e737d5e332..c4ad07c9ae 100644 --- a/OvmfPkg/VirtioFsDxe/SimpleFsRead.c +++ b/OvmfPkg/VirtioFsDxe/SimpleFsRead.c @@ -8,6 +8,69 @@ #include "VirtioFsDxe.h" +/** + Read from a regular file. +**/ +STATIC +EFI_STATUS +ReadRegularFile ( + IN OUT VIRTIO_FS_FILE *VirtioFsFile, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + VIRTIO_FS *VirtioFs; + EFI_STATUS Status; + VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr; + UINTN Transferred; + UINTN Left; + + VirtioFs = VirtioFsFile->OwnerFs; + // + // The UEFI spec forbids reads that start beyond the end of the file. + // + Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr); + if (EFI_ERROR (Status) || VirtioFsFile->FilePosition > FuseAttr.Size) { + return EFI_DEVICE_ERROR; + } + + Status = EFI_SUCCESS; + Transferred = 0; + Left = *BufferSize; + while (Left > 0) { + UINT32 ReadSize; + + // + // FUSE_READ cannot express a >=4GB buffer size. + // + ReadSize = (UINT32)MIN ((UINTN)MAX_UINT32, Left); + Status = VirtioFsFuseReadFileOrDir ( + VirtioFs, + VirtioFsFile->NodeId, + VirtioFsFile->FuseHandle, + FALSE, // IsDir + VirtioFsFile->FilePosition + Transferred, + &ReadSize, + (UINT8 *)Buffer + Transferred + ); + if (EFI_ERROR (Status) || ReadSize == 0) { + break; + } + Transferred += ReadSize; + Left -= ReadSize; + } + + *BufferSize = Transferred; + VirtioFsFile->FilePosition += Transferred; + // + // If we managed to read some data, return success. If zero bytes were + // transferred due to zero-sized buffer on input or due to EOF on first read, + // return SUCCESS. Otherwise, return the error due to which zero bytes were + // transferred. + // + return (Transferred > 0) ? EFI_SUCCESS : Status; +} + EFI_STATUS EFIAPI VirtioFsSimpleFileRead ( @@ -16,5 +79,15 @@ VirtioFsSimpleFileRead ( OUT VOID *Buffer ) { - return EFI_NO_MEDIA; + VIRTIO_FS_FILE *VirtioFsFile; + EFI_STATUS Status; + + VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This); + + if (VirtioFsFile->IsDirectory) { + Status = EFI_NO_MEDIA; + } else { + Status = ReadRegularFile (VirtioFsFile, BufferSize, Buffer); + } + return Status; }