]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c
OvmfPkg/VirtioFsDxe: implement EFI_FILE_PROTOCOL.GetInfo()
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / SimpleFsGetInfo.c
1 /** @file
2 EFI_FILE_PROTOCOL.GetInfo() member function for the Virtio Filesystem driver.
3
4 Copyright (C) 2020, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Guid/FileSystemInfo.h> // gEfiFileSystemInfoGuid
10 #include <Guid/FileSystemVolumeLabelInfo.h> // gEfiFileSystemVolumeLabelInfo...
11 #include <Library/BaseLib.h> // StrSize()
12 #include <Library/BaseMemoryLib.h> // CompareGuid()
13
14 #include "VirtioFsDxe.h"
15
16 /**
17 Provide EFI_FILE_INFO about this particular file.
18 **/
19 STATIC
20 EFI_STATUS
21 GetFileInfo (
22 IN EFI_FILE_PROTOCOL *This,
23 IN OUT UINTN *BufferSize,
24 OUT VOID *Buffer
25 )
26 {
27 VIRTIO_FS_FILE *VirtioFsFile;
28 VIRTIO_FS *VirtioFs;
29 UINTN AllocSize;
30 UINTN BasenameSize;
31 EFI_STATUS Status;
32 EFI_FILE_INFO *FileInfo;
33 VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
34
35 VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
36 VirtioFs = VirtioFsFile->OwnerFs;
37
38 AllocSize = *BufferSize;
39
40 //
41 // Calculate the needed size.
42 //
43 BasenameSize = 0;
44 Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname, NULL,
45 &BasenameSize);
46 ASSERT (Status == EFI_BUFFER_TOO_SMALL);
47 *BufferSize = OFFSET_OF (EFI_FILE_INFO, FileName) + BasenameSize;
48
49 if (*BufferSize > AllocSize) {
50 return EFI_BUFFER_TOO_SMALL;
51 }
52
53 //
54 // Set the structure size, and store the basename.
55 //
56 FileInfo = Buffer;
57 FileInfo->Size = *BufferSize;
58 Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname,
59 FileInfo->FileName, &BasenameSize);
60 ASSERT_EFI_ERROR (Status);
61
62 //
63 // Fetch the file attributes, and convert them into the caller's buffer.
64 //
65 Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
66 if (!EFI_ERROR (Status)) {
67 Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, FileInfo);
68 }
69 return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;
70 }
71
72 /**
73 Provide EFI_FILE_SYSTEM_INFO about the filesystem this file lives on.
74 **/
75 STATIC
76 EFI_STATUS
77 GetFileSystemInfo (
78 IN EFI_FILE_PROTOCOL *This,
79 IN OUT UINTN *BufferSize,
80 OUT VOID *Buffer
81 )
82 {
83 VIRTIO_FS_FILE *VirtioFsFile;
84 VIRTIO_FS *VirtioFs;
85 UINTN AllocSize;
86 UINTN LabelSize;
87 EFI_STATUS Status;
88 VIRTIO_FS_FUSE_STATFS_RESPONSE FilesysAttr;
89 UINT64 MaxBlocks;
90 EFI_FILE_SYSTEM_INFO *FilesysInfo;
91
92 VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
93 VirtioFs = VirtioFsFile->OwnerFs;
94
95 AllocSize = *BufferSize;
96
97 //
98 // Calculate the needed size.
99 //
100 LabelSize = StrSize (VirtioFs->Label);
101 *BufferSize = OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel) + LabelSize;
102
103 if (*BufferSize > AllocSize) {
104 return EFI_BUFFER_TOO_SMALL;
105 }
106
107 //
108 // Fetch the filesystem attributes.
109 //
110 Status = VirtioFsFuseStatFs (VirtioFs, VirtioFsFile->NodeId, &FilesysAttr);
111 if (EFI_ERROR (Status)) {
112 return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;
113 }
114 //
115 // Sanity checks...
116 //
117 if (FilesysAttr.Frsize != FilesysAttr.Bsize) {
118 return EFI_UNSUPPORTED;
119 }
120 if (FilesysAttr.Frsize == 0 || FilesysAttr.Blocks == 0 ||
121 FilesysAttr.Bavail > FilesysAttr.Blocks) {
122 return EFI_DEVICE_ERROR;
123 }
124 MaxBlocks = DivU64x32 (MAX_UINT64, FilesysAttr.Frsize);
125 if (FilesysAttr.Blocks > MaxBlocks || FilesysAttr.Bavail > MaxBlocks) {
126 return EFI_DEVICE_ERROR;
127 }
128
129 //
130 // Fill in EFI_FILE_SYSTEM_INFO.
131 //
132 FilesysInfo = Buffer;
133 FilesysInfo->Size = *BufferSize;
134 FilesysInfo->ReadOnly = FALSE;
135 FilesysInfo->VolumeSize = MultU64x32 (FilesysAttr.Blocks,
136 FilesysAttr.Frsize);
137 FilesysInfo->FreeSpace = MultU64x32 (FilesysAttr.Bavail,
138 FilesysAttr.Frsize);
139 FilesysInfo->BlockSize = FilesysAttr.Frsize;
140 CopyMem (FilesysInfo->VolumeLabel, VirtioFs->Label, LabelSize);
141
142 return EFI_SUCCESS;
143 }
144
145 /**
146 Return the filesystem label as EFI_FILE_SYSTEM_VOLUME_LABEL.
147 **/
148 STATIC
149 EFI_STATUS
150 GetFileSystemVolumeLabelInfo (
151 IN EFI_FILE_PROTOCOL *This,
152 IN OUT UINTN *BufferSize,
153 OUT VOID *Buffer
154 )
155 {
156 VIRTIO_FS_FILE *VirtioFsFile;
157 VIRTIO_FS *VirtioFs;
158 UINTN AllocSize;
159 UINTN LabelSize;
160 EFI_FILE_SYSTEM_VOLUME_LABEL *FilesysVolumeLabel;
161
162 VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
163 VirtioFs = VirtioFsFile->OwnerFs;
164
165 AllocSize = *BufferSize;
166
167 //
168 // Calculate the needed size.
169 //
170 LabelSize = StrSize (VirtioFs->Label);
171 *BufferSize = (OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel) +
172 LabelSize);
173
174 if (*BufferSize > AllocSize) {
175 return EFI_BUFFER_TOO_SMALL;
176 }
177
178 //
179 // Store the label.
180 //
181 FilesysVolumeLabel = Buffer;
182 CopyMem (FilesysVolumeLabel->VolumeLabel, VirtioFs->Label, LabelSize);
183
184 return EFI_SUCCESS;
185 }
186
187 EFI_STATUS
188 EFIAPI
189 VirtioFsSimpleFileGetInfo (
190 IN EFI_FILE_PROTOCOL *This,
191 IN EFI_GUID *InformationType,
192 IN OUT UINTN *BufferSize,
193 OUT VOID *Buffer
194 )
195 {
196 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
197 return GetFileInfo (This, BufferSize, Buffer);
198 }
199
200 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
201 return GetFileSystemInfo (This, BufferSize, Buffer);
202 }
203
204 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
205 return GetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);
206 }
207
208 return EFI_UNSUPPORTED;
209 }