diff --git a/OvmfPkg/Include/IndustryStandard/VirtioFs.h b/OvmfPkg/Include/IndustryStandard/VirtioFs.h index 63aced229e..5d1d990a2d 100644 --- a/OvmfPkg/Include/IndustryStandard/VirtioFs.h +++ b/OvmfPkg/Include/IndustryStandard/VirtioFs.h @@ -84,6 +84,9 @@ typedef struct { // // File mode bitmasks. // +#define VIRTIO_FS_FUSE_MODE_TYPE_MASK 0170000u +#define VIRTIO_FS_FUSE_MODE_TYPE_REG 0100000u +#define VIRTIO_FS_FUSE_MODE_TYPE_DIR 0040000u #define VIRTIO_FS_FUSE_MODE_PERM_RWXU 0000700u #define VIRTIO_FS_FUSE_MODE_PERM_RUSR 0000400u #define VIRTIO_FS_FUSE_MODE_PERM_WUSR 0000200u diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 4ff70674fb..26a013ec35 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -125,6 +125,7 @@ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf BaseLib|MdePkg/Library/BaseLib/BaseLib.inf SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index d40a59183c..10579fe46c 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -129,6 +129,7 @@ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf BaseLib|MdePkg/Library/BaseLib/BaseLib.inf SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index ec7886235a..c9235e48ad 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -129,6 +129,7 @@ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf BaseLib|MdePkg/Library/BaseLib/BaseLib.inf SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf diff --git a/OvmfPkg/VirtioFsDxe/Helpers.c b/OvmfPkg/VirtioFsDxe/Helpers.c index 8ffdabfd40..e9582e46bd 100644 --- a/OvmfPkg/VirtioFsDxe/Helpers.c +++ b/OvmfPkg/VirtioFsDxe/Helpers.c @@ -9,6 +9,7 @@ #include // StrLen() #include // CopyMem() #include // AllocatePool() +#include // EpochToEfiTime() #include // Virtio10WriteFeatures() #include "VirtioFsDxe.h" @@ -1589,3 +1590,121 @@ FreeRhsPath8: FreePool (RhsPath8); return Status; } + +/** + Convert select fields of a VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to + corresponding fields in EFI_FILE_INFO. + + @param[in] FuseAttr The VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to + convert the relevant fields from. + + @param[out] FileInfo The EFI_FILE_INFO structure to modify. Importantly, the + FileInfo->Size and FileInfo->FileName fields are not + overwritten. + + @retval EFI_SUCCESS Conversion successful. + + @retval EFI_UNSUPPORTED The allocated size of the file is inexpressible in + EFI_FILE_INFO. + + @retval EFI_UNSUPPORTED One of the file access times is inexpressible in + EFI_FILE_INFO. + + @retval EFI_UNSUPPORTED The file type is inexpressible in EFI_FILE_INFO. + + @retval EFI_UNSUPPORTED The file is a regular file that has multiple names + on the host side (i.e., its hard link count is + greater than one). +**/ +EFI_STATUS +VirtioFsFuseAttrToEfiFileInfo ( + IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr, + OUT EFI_FILE_INFO *FileInfo + ) +{ + UINT64 EpochTime[3]; + EFI_TIME *ConvertedTime[ARRAY_SIZE (EpochTime)]; + UINTN Idx; + + FileInfo->FileSize = FuseAttr->Size; + + // + // The unit for FuseAttr->Blocks is 512B. + // + if (FuseAttr->Blocks >= BIT55) { + return EFI_UNSUPPORTED; + } + FileInfo->PhysicalSize = LShiftU64 (FuseAttr->Blocks, 9); + + // + // Convert the timestamps. File creation time is not tracked by the Virtio + // Filesystem device, so set FileInfo->CreateTime from FuseAttr->Mtime as + // well. + // + EpochTime[0] = FuseAttr->Mtime; + EpochTime[1] = FuseAttr->Atime; + EpochTime[2] = FuseAttr->Mtime; + ConvertedTime[0] = &FileInfo->CreateTime; + ConvertedTime[1] = &FileInfo->LastAccessTime; + ConvertedTime[2] = &FileInfo->ModificationTime; + + for (Idx = 0; Idx < ARRAY_SIZE (EpochTime); Idx++) { + // + // EpochToEfiTime() takes a UINTN for seconds. + // + if (EpochTime[Idx] > MAX_UINTN) { + return EFI_UNSUPPORTED; + } + // + // Set the following fields in the converted time: Year, Month, Day, Hour, + // Minute, Second, Nanosecond. + // + EpochToEfiTime ((UINTN)EpochTime[Idx], ConvertedTime[Idx]); + // + // The times are all expressed in UTC. Consequently, they are not affected + // by daylight saving. + // + ConvertedTime[Idx]->TimeZone = 0; + ConvertedTime[Idx]->Daylight = 0; + // + // Clear the padding fields. + // + ConvertedTime[Idx]->Pad1 = 0; + ConvertedTime[Idx]->Pad2 = 0; + } + + // + // Set the attributes. + // + switch (FuseAttr->Mode & VIRTIO_FS_FUSE_MODE_TYPE_MASK) { + case VIRTIO_FS_FUSE_MODE_TYPE_DIR: + FileInfo->Attribute = EFI_FILE_DIRECTORY; + break; + case VIRTIO_FS_FUSE_MODE_TYPE_REG: + FileInfo->Attribute = 0; + break; + default: + // + // Other file types are not supported. + // + return EFI_UNSUPPORTED; + } + // + // Report the regular file or directory as read-only if all classes lack + // write permission. + // + if ((FuseAttr->Mode & (VIRTIO_FS_FUSE_MODE_PERM_WUSR | + VIRTIO_FS_FUSE_MODE_PERM_WGRP | + VIRTIO_FS_FUSE_MODE_PERM_WOTH)) == 0) { + FileInfo->Attribute |= EFI_FILE_READ_ONLY; + } + + // + // A hard link count greater than 1 is not supported for regular files. + // + if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && FuseAttr->Nlink > 1) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h index 795cf4ee5d..6cc5257bab 100644 --- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h +++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h @@ -11,6 +11,7 @@ #define VIRTIO_FS_DXE_H_ #include // SIGNATURE_64() +#include // EFI_FILE_INFO #include // VIRTIO_FS_TAG_BYTES #include // CR() #include // EFI_SIMPLE_FILE_SYSTEM_PROTOCOL @@ -225,6 +226,12 @@ VirtioFsAppendPath ( OUT BOOLEAN *RootEscape ); +EFI_STATUS +VirtioFsFuseAttrToEfiFileInfo ( + IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr, + OUT EFI_FILE_INFO *FileInfo + ); + // // Wrapper functions for FUSE commands (primitives). // diff --git a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf index b942baa4a7..7d72721884 100644 --- a/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf +++ b/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf @@ -77,6 +77,7 @@ ENTRY_POINT = VirtioFsEntryPoint [Packages] + EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec OvmfPkg/OvmfPkg.dec @@ -110,6 +111,7 @@ BaseMemoryLib DebugLib MemoryAllocationLib + TimeBaseLib UefiBootServicesTableLib UefiDriverEntryPoint VirtioLib