]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.GetInfo()
authorLaszlo Ersek <lersek@redhat.com>
Wed, 16 Dec 2020 21:11:07 +0000 (22:11 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 21 Dec 2020 17:16:23 +0000 (17:16 +0000)
Using the functions introduced previously, we can now implement
VirtioFsSimpleFileGetInfo().

This allows the "VOL" command to work in the UEFI shell.

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-31-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c
OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf

index 6e870460c014bd32867670626e7eb12d737eac7f..c8be1d502202d8a449956a70288b80ac8e537afc 100644 (file)
@@ -6,8 +6,184 @@
   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
@@ -17,5 +193,17 @@ VirtioFsSimpleFileGetInfo (
      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
index 318449db3e63ddb4b2ee268677f263e7ecb24f6d..3cb5c101c3a6e8a3ee2f92a9e752d4d23d3308a8 100644 (file)
   gEfiDriverBindingProtocolGuid         ## PRODUCES\r
   gEfiSimpleFileSystemProtocolGuid      ## BY_START\r
   gVirtioDeviceProtocolGuid             ## TO_START\r
+\r
+[Guids]\r
+  gEfiFileInfoGuid\r
+  gEfiFileSystemInfoGuid\r
+  gEfiFileSystemVolumeLabelInfoIdGuid\r