OvmfPkg/VirtioFsDxe: implement EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume()

With the help of the VirtioFsFuseOpenDir() and
VirtioFsFuseReleaseFileOrDir() functions introduced previously, we can now
open and close the root directory. So let's implement
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume().

OpenVolume() creates a new EFI_FILE_PROTOCOL object -- a reference to the
root directory of the filesystem. Thus, we have to start tracking
references to EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, lest we unbind the
virtio-fs device while files are open.

There are two methods that release an EFI_FILE_PROTOCOL object: the
Close() and the Delete() member functions. In particular, they are not
allowed to fail with regard to resource management -- they must release
resources unconditionally. Thus, for rolling back the resource accounting
that we do in EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume(), we have to
implement the first versions of EFI_FILE_PROTOCOL.Close() and
EFI_FILE_PROTOCOL.Delete() in this patch as well.

With this patch applied, the UEFI shell can enter the root directory of
the Virtio Filesystem (such as with the "FS3:" shell command), and the
"DIR" shell command exercises FUSE_OPENDIR and FUSE_RELEASEDIR, according
to the virtiofsd log. The "DIR" command reports the root directory as if
it were empty; probably because at this time, we only allow the shell to
open and to close the root directory, but not to read it.

Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3097
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20201216211125.19496-12-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
This commit is contained in:
Laszlo Ersek
2020-12-16 22:10:48 +01:00
committed by mergify[bot]
parent 72d4f133e9
commit 334c13e106
15 changed files with 432 additions and 1 deletions

View File

@@ -19,6 +19,9 @@
#define VIRTIO_FS_SIG SIGNATURE_64 ('V', 'I', 'R', 'T', 'I', 'O', 'F', 'S')
#define VIRTIO_FS_FILE_SIG \
SIGNATURE_64 ('V', 'I', 'O', 'F', 'S', 'F', 'I', 'L')
//
// Filesystem label encoded in UCS-2, transformed from the UTF-8 representation
// in "VIRTIO_FS_CONFIG.Tag", and NUL-terminated. Only the printable ASCII code
@@ -46,6 +49,7 @@ typedef struct {
VOID *RingMap; // VirtioRingMap 2
UINT64 RequestId; // FuseInitSession 1
EFI_EVENT ExitBoot; // DriverBindingStart 0
LIST_ENTRY OpenFiles; // DriverBindingStart 0
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs; // DriverBindingStart 0
} VIRTIO_FS;
@@ -98,6 +102,39 @@ typedef struct {
UINT32 TotalSize;
} VIRTIO_FS_SCATTER_GATHER_LIST;
//
// Private context structure that exposes EFI_FILE_PROTOCOL on top of an open
// FUSE file reference.
//
typedef struct {
UINT64 Signature;
EFI_FILE_PROTOCOL SimpleFile;
BOOLEAN IsDirectory;
VIRTIO_FS *OwnerFs;
LIST_ENTRY OpenFilesEntry;
//
// In the FUSE wire protocol, every request except FUSE_INIT refers to a
// file, namely by the "VIRTIO_FS_FUSE_REQUEST.NodeId" field; that is, by the
// inode number of the file. However, some of the FUSE requests that we need
// for some of the EFI_FILE_PROTOCOL member functions require an open file
// handle *in addition* to the inode number. For simplicity, whenever a
// VIRTIO_FS_FILE object is created, primarily defined by its NodeId field,
// we also *open* the referenced file at once, and save the returned file
// handle in the FuseHandle field. This way, when an EFI_FILE_PROTOCOL member
// function must send a FUSE request that needs the file handle *in addition*
// to the inode number, FuseHandle will be at our disposal at once.
//
UINT64 NodeId;
UINT64 FuseHandle;
} VIRTIO_FS_FILE;
#define VIRTIO_FS_FILE_FROM_SIMPLE_FILE(SimpleFileReference) \
CR (SimpleFileReference, VIRTIO_FS_FILE, SimpleFile, VIRTIO_FS_FILE_SIG);
#define VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY(OpenFilesEntryReference) \
CR (OpenFilesEntryReference, VIRTIO_FS_FILE, OpenFilesEntry, \
VIRTIO_FS_FILE_SIG);
//
// Initialization and helper routines for the Virtio Filesystem device.
//
@@ -190,4 +227,84 @@ VirtioFsOpenVolume (
OUT EFI_FILE_PROTOCOL **Root
);
//
// EFI_FILE_PROTOCOL member functions for the Virtio Filesystem driver.
//
EFI_STATUS
EFIAPI
VirtioFsSimpleFileClose (
IN EFI_FILE_PROTOCOL *This
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileDelete (
IN EFI_FILE_PROTOCOL *This
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileFlush (
IN EFI_FILE_PROTOCOL *This
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileGetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileGetPosition (
IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileOpen (
IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileRead (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileSetInfo (
IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType,
IN UINTN BufferSize,
IN VOID *Buffer
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileSetPosition (
IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position
);
EFI_STATUS
EFIAPI
VirtioFsSimpleFileWrite (
IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
);
#endif // VIRTIO_FS_DXE_H_