SPDX-License-Identifier: BSD-2-Clause-Patent\r
**/\r
\r
+#include <Guid/FileSystemInfo.h> // gEfiFileSystemInfoGuid\r
+#include <Guid/FileSystemVolumeLabelInfo.h> // gEfiFileSystemVolumeLabelInfo...\r
+#include <Library/BaseLib.h> // StrSize()\r
+#include <Library/BaseMemoryLib.h> // CompareGuid()\r
+\r
#include "VirtioFsDxe.h"\r
\r
+/**\r
+ Provide EFI_FILE_INFO about this particular file.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetFileInfo (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ VIRTIO_FS_FILE *VirtioFsFile;\r
+ VIRTIO_FS *VirtioFs;\r
+ UINTN AllocSize;\r
+ UINTN BasenameSize;\r
+ EFI_STATUS Status;\r
+ EFI_FILE_INFO *FileInfo;\r
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
+\r
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r
+ VirtioFs = VirtioFsFile->OwnerFs;\r
+\r
+ AllocSize = *BufferSize;\r
+\r
+ //\r
+ // Calculate the needed size.\r
+ //\r
+ BasenameSize = 0;\r
+ Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname, NULL,\r
+ &BasenameSize);\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+ *BufferSize = OFFSET_OF (EFI_FILE_INFO, FileName) + BasenameSize;\r
+\r
+ if (*BufferSize > AllocSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ //\r
+ // Set the structure size, and store the basename.\r
+ //\r
+ FileInfo = Buffer;\r
+ FileInfo->Size = *BufferSize;\r
+ Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname,\r
+ FileInfo->FileName, &BasenameSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Fetch the file attributes, and convert them into the caller's buffer.\r
+ //\r
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, FileInfo);\r
+ }\r
+ return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;\r
+}\r
+\r
+/**\r
+ Provide EFI_FILE_SYSTEM_INFO about the filesystem this file lives on.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetFileSystemInfo (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ VIRTIO_FS_FILE *VirtioFsFile;\r
+ VIRTIO_FS *VirtioFs;\r
+ UINTN AllocSize;\r
+ UINTN LabelSize;\r
+ EFI_STATUS Status;\r
+ VIRTIO_FS_FUSE_STATFS_RESPONSE FilesysAttr;\r
+ UINT64 MaxBlocks;\r
+ EFI_FILE_SYSTEM_INFO *FilesysInfo;\r
+\r
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r
+ VirtioFs = VirtioFsFile->OwnerFs;\r
+\r
+ AllocSize = *BufferSize;\r
+\r
+ //\r
+ // Calculate the needed size.\r
+ //\r
+ LabelSize = StrSize (VirtioFs->Label);\r
+ *BufferSize = OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel) + LabelSize;\r
+\r
+ if (*BufferSize > AllocSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ //\r
+ // Fetch the filesystem attributes.\r
+ //\r
+ Status = VirtioFsFuseStatFs (VirtioFs, VirtioFsFile->NodeId, &FilesysAttr);\r
+ if (EFI_ERROR (Status)) {\r
+ return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;\r
+ }\r
+ //\r
+ // Sanity checks...\r
+ //\r
+ if (FilesysAttr.Frsize != FilesysAttr.Bsize) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ if (FilesysAttr.Frsize == 0 || FilesysAttr.Blocks == 0 ||\r
+ FilesysAttr.Bavail > FilesysAttr.Blocks) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ MaxBlocks = DivU64x32 (MAX_UINT64, FilesysAttr.Frsize);\r
+ if (FilesysAttr.Blocks > MaxBlocks || FilesysAttr.Bavail > MaxBlocks) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Fill in EFI_FILE_SYSTEM_INFO.\r
+ //\r
+ FilesysInfo = Buffer;\r
+ FilesysInfo->Size = *BufferSize;\r
+ FilesysInfo->ReadOnly = FALSE;\r
+ FilesysInfo->VolumeSize = MultU64x32 (FilesysAttr.Blocks,\r
+ FilesysAttr.Frsize);\r
+ FilesysInfo->FreeSpace = MultU64x32 (FilesysAttr.Bavail,\r
+ FilesysAttr.Frsize);\r
+ FilesysInfo->BlockSize = FilesysAttr.Frsize;\r
+ CopyMem (FilesysInfo->VolumeLabel, VirtioFs->Label, LabelSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return the filesystem label as EFI_FILE_SYSTEM_VOLUME_LABEL.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+GetFileSystemVolumeLabelInfo (\r
+ IN EFI_FILE_PROTOCOL *This,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ VIRTIO_FS_FILE *VirtioFsFile;\r
+ VIRTIO_FS *VirtioFs;\r
+ UINTN AllocSize;\r
+ UINTN LabelSize;\r
+ EFI_FILE_SYSTEM_VOLUME_LABEL *FilesysVolumeLabel;\r
+\r
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r
+ VirtioFs = VirtioFsFile->OwnerFs;\r
+\r
+ AllocSize = *BufferSize;\r
+\r
+ //\r
+ // Calculate the needed size.\r
+ //\r
+ LabelSize = StrSize (VirtioFs->Label);\r
+ *BufferSize = (OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel) +\r
+ LabelSize);\r
+\r
+ if (*BufferSize > AllocSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ //\r
+ // Store the label.\r
+ //\r
+ FilesysVolumeLabel = Buffer;\r
+ CopyMem (FilesysVolumeLabel->VolumeLabel, VirtioFs->Label, LabelSize);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
EFI_STATUS\r
EFIAPI\r
VirtioFsSimpleFileGetInfo (\r
OUT VOID *Buffer\r
)\r
{\r
- return EFI_NO_MEDIA;\r
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+ return GetFileInfo (This, BufferSize, Buffer);\r
+ }\r
+\r
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
+ return GetFileSystemInfo (This, BufferSize, Buffer);\r
+ }\r
+\r
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
+ return GetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);\r
+ }\r
+\r
+ return EFI_UNSUPPORTED;\r
}\r