]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VirtioFsDxe: convert FUSE inode attributes to EFI_FILE_INFO
authorLaszlo Ersek <lersek@redhat.com>
Wed, 16 Dec 2020 21:10:58 +0000 (22:10 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 21 Dec 2020 17:16:23 +0000 (17:16 +0000)
Introduce the VirtioFsFuseAttrToEfiFileInfo() function, for converting
FUSE inode attributes to EFI_FILE_INFO.

The EpochToEfiTime() function from EmbeddedPkg's TimeBaseLib proves
invaluable for converting the file access times.

This is the first time we consume TimeBaseLib in OvmfPkg, so add the
necessary lib class resolution. We need not modify any ArmVirtPkg DSC
files: see commit af5fed90bfbf ("ArmPlatformPkg,ArmVirtPkg: delete
redundant PL031 functions", 2017-05-10).

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-22-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
OvmfPkg/Include/IndustryStandard/VirtioFs.h
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/VirtioFsDxe/Helpers.c
OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf

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