#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
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