]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioFsDxe/SimpleFsRead.c
OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.Read() for regular files
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / SimpleFsRead.c
1 /** @file
2 EFI_FILE_PROTOCOL.Read() member function for the Virtio Filesystem driver.
3
4 Copyright (C) 2020, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include "VirtioFsDxe.h"
10
11 /**
12 Read from a regular file.
13 **/
14 STATIC
15 EFI_STATUS
16 ReadRegularFile (
17 IN OUT VIRTIO_FS_FILE *VirtioFsFile,
18 IN OUT UINTN *BufferSize,
19 OUT VOID *Buffer
20 )
21 {
22 VIRTIO_FS *VirtioFs;
23 EFI_STATUS Status;
24 VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
25 UINTN Transferred;
26 UINTN Left;
27
28 VirtioFs = VirtioFsFile->OwnerFs;
29 //
30 // The UEFI spec forbids reads that start beyond the end of the file.
31 //
32 Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
33 if (EFI_ERROR (Status) || VirtioFsFile->FilePosition > FuseAttr.Size) {
34 return EFI_DEVICE_ERROR;
35 }
36
37 Status = EFI_SUCCESS;
38 Transferred = 0;
39 Left = *BufferSize;
40 while (Left > 0) {
41 UINT32 ReadSize;
42
43 //
44 // FUSE_READ cannot express a >=4GB buffer size.
45 //
46 ReadSize = (UINT32)MIN ((UINTN)MAX_UINT32, Left);
47 Status = VirtioFsFuseReadFileOrDir (
48 VirtioFs,
49 VirtioFsFile->NodeId,
50 VirtioFsFile->FuseHandle,
51 FALSE, // IsDir
52 VirtioFsFile->FilePosition + Transferred,
53 &ReadSize,
54 (UINT8 *)Buffer + Transferred
55 );
56 if (EFI_ERROR (Status) || ReadSize == 0) {
57 break;
58 }
59 Transferred += ReadSize;
60 Left -= ReadSize;
61 }
62
63 *BufferSize = Transferred;
64 VirtioFsFile->FilePosition += Transferred;
65 //
66 // If we managed to read some data, return success. If zero bytes were
67 // transferred due to zero-sized buffer on input or due to EOF on first read,
68 // return SUCCESS. Otherwise, return the error due to which zero bytes were
69 // transferred.
70 //
71 return (Transferred > 0) ? EFI_SUCCESS : Status;
72 }
73
74 EFI_STATUS
75 EFIAPI
76 VirtioFsSimpleFileRead (
77 IN EFI_FILE_PROTOCOL *This,
78 IN OUT UINTN *BufferSize,
79 OUT VOID *Buffer
80 )
81 {
82 VIRTIO_FS_FILE *VirtioFsFile;
83 EFI_STATUS Status;
84
85 VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
86
87 if (VirtioFsFile->IsDirectory) {
88 Status = EFI_NO_MEDIA;
89 } else {
90 Status = ReadRegularFile (VirtioFsFile, BufferSize, Buffer);
91 }
92 return Status;
93 }