1 | /** @file
|
---|
2 | EFI_FILE_PROTOCOL.SetInfo() 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> // StrCmp()
|
---|
12 | #include <Library/BaseMemoryLib.h> // CompareGuid()
|
---|
13 | #include <Library/MemoryAllocationLib.h> // FreePool()
|
---|
14 |
|
---|
15 | #include "VirtioFsDxe.h"
|
---|
16 |
|
---|
17 | /**
|
---|
18 | Validate a buffer that the EFI_FILE_PROTOCOL.SetInfo() caller passes in for a
|
---|
19 | particular InformationType GUID.
|
---|
20 |
|
---|
21 | The structure to be validated is supposed to end with a variable-length,
|
---|
22 | NUL-terminated CHAR16 Name string.
|
---|
23 |
|
---|
24 | @param[in] SizeByProtocolCaller The BufferSize parameter as provided by the
|
---|
25 | EFI_FILE_PROTOCOL.SetInfo() caller.
|
---|
26 |
|
---|
27 | @param[in] MinimumStructSize The minimum structure size that is required
|
---|
28 | for the given InformationType GUID,
|
---|
29 | including a single CHAR16 element from the
|
---|
30 | trailing Name field.
|
---|
31 |
|
---|
32 | @param[in] IsSizeByInfoPresent TRUE if and only if the expected structure
|
---|
33 | starts with a UINT64 Size field that reports
|
---|
34 | the actual structure size.
|
---|
35 |
|
---|
36 | @param[in] Buffer The Buffer parameter as provided by the
|
---|
37 | EFI_FILE_PROTOCOL.SetInfo() caller.
|
---|
38 |
|
---|
39 | @retval EFI_SUCCESS Validation successful, Buffer is well-formed.
|
---|
40 |
|
---|
41 | @retval EFI_BAD_BUFFER_SIZE The EFI_FILE_PROTOCOL.SetInfo()
|
---|
42 | caller provided a BufferSize that is smaller
|
---|
43 | than the minimum structure size required for
|
---|
44 | the given InformationType GUID.
|
---|
45 |
|
---|
46 | @retval EFI_INVALID_PARAMETER IsSizeByInfoPresent is TRUE, and the leading
|
---|
47 | UINT64 Size field does not match the
|
---|
48 | EFI_FILE_PROTOCOL.SetInfo() caller-provided
|
---|
49 | BufferSize.
|
---|
50 |
|
---|
51 | @retval EFI_INVALID_PARAMETER The trailing Name field does not consist of a
|
---|
52 | whole multiple of CHAR16 elements.
|
---|
53 |
|
---|
54 | @retval EFI_INVALID_PARAMETER The trailing Name field is not NUL-terminated.
|
---|
55 | **/
|
---|
56 | STATIC
|
---|
57 | EFI_STATUS
|
---|
58 | ValidateInfoStructure (
|
---|
59 | IN UINTN SizeByProtocolCaller,
|
---|
60 | IN UINTN MinimumStructSize,
|
---|
61 | IN BOOLEAN IsSizeByInfoPresent,
|
---|
62 | IN VOID *Buffer
|
---|
63 | )
|
---|
64 | {
|
---|
65 | UINTN NameFieldByteOffset;
|
---|
66 | UINTN NameFieldBytes;
|
---|
67 | UINTN NameFieldChar16s;
|
---|
68 | CHAR16 *NameField;
|
---|
69 |
|
---|
70 | //
|
---|
71 | // Make sure the internal function asking for validation passes in sane
|
---|
72 | // values.
|
---|
73 | //
|
---|
74 | ASSERT (MinimumStructSize >= sizeof (CHAR16));
|
---|
75 | NameFieldByteOffset = MinimumStructSize - sizeof (CHAR16);
|
---|
76 |
|
---|
77 | if (IsSizeByInfoPresent) {
|
---|
78 | ASSERT (MinimumStructSize >= sizeof (UINT64) + sizeof (CHAR16));
|
---|
79 | ASSERT (NameFieldByteOffset >= sizeof (UINT64));
|
---|
80 | }
|
---|
81 |
|
---|
82 | //
|
---|
83 | // Check whether the protocol caller provided enough bytes for the minimum
|
---|
84 | // size of this info structure.
|
---|
85 | //
|
---|
86 | if (SizeByProtocolCaller < MinimumStructSize) {
|
---|
87 | return EFI_BAD_BUFFER_SIZE;
|
---|
88 | }
|
---|
89 |
|
---|
90 | //
|
---|
91 | // If the info structure starts with a UINT64 Size field, check if that
|
---|
92 | // agrees with the protocol caller-provided size.
|
---|
93 | //
|
---|
94 | if (IsSizeByInfoPresent) {
|
---|
95 | UINT64 *SizeByInfo;
|
---|
96 |
|
---|
97 | SizeByInfo = Buffer;
|
---|
98 | if (*SizeByInfo != SizeByProtocolCaller) {
|
---|
99 | return EFI_INVALID_PARAMETER;
|
---|
100 | }
|
---|
101 | }
|
---|
102 |
|
---|
103 | //
|
---|
104 | // The CHAR16 Name field at the end of the structure must have an even number
|
---|
105 | // of bytes.
|
---|
106 | //
|
---|
107 | // The subtraction below cannot underflow, and yields at least
|
---|
108 | // sizeof(CHAR16).
|
---|
109 | //
|
---|
110 | ASSERT (SizeByProtocolCaller >= NameFieldByteOffset);
|
---|
111 | NameFieldBytes = SizeByProtocolCaller - NameFieldByteOffset;
|
---|
112 | ASSERT (NameFieldBytes >= sizeof (CHAR16));
|
---|
113 | if (NameFieldBytes % sizeof (CHAR16) != 0) {
|
---|
114 | return EFI_INVALID_PARAMETER;
|
---|
115 | }
|
---|
116 |
|
---|
117 | //
|
---|
118 | // The CHAR16 Name field at the end of the structure must be NUL-terminated.
|
---|
119 | //
|
---|
120 | NameFieldChar16s = NameFieldBytes / sizeof (CHAR16);
|
---|
121 | ASSERT (NameFieldChar16s >= 1);
|
---|
122 |
|
---|
123 | NameField = (CHAR16 *)((UINT8 *)Buffer + NameFieldByteOffset);
|
---|
124 | if (NameField[NameFieldChar16s - 1] != L'\0') {
|
---|
125 | return EFI_INVALID_PARAMETER;
|
---|
126 | }
|
---|
127 |
|
---|
128 | return EFI_SUCCESS;
|
---|
129 | }
|
---|
130 |
|
---|
131 | /**
|
---|
132 | Rename a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.FileName.
|
---|
133 |
|
---|
134 | @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to rename.
|
---|
135 |
|
---|
136 | @param[in] NewFileName The new file name requested by
|
---|
137 | EFI_FILE_PROTOCOL.SetInfo().
|
---|
138 |
|
---|
139 | @retval EFI_SUCCESS The canonical format destination path that is
|
---|
140 | determined from the input value of
|
---|
141 | VirtioFsFile->CanonicalPathname and from
|
---|
142 | NewFileName is identical to the input value of
|
---|
143 | VirtioFsFile->CanonicalPathname. This means that
|
---|
144 | EFI_FILE_INFO does not constitute a rename
|
---|
145 | request. VirtioFsFile has not been changed.
|
---|
146 |
|
---|
147 | @retval EFI_SUCCESS VirtioFsFile has been renamed.
|
---|
148 | VirtioFsFile->CanonicalPathname has assumed the
|
---|
149 | destination pathname in canonical format.
|
---|
150 |
|
---|
151 | @retval EFI_ACCESS_DENIED VirtioFsFile refers to the root directory, and
|
---|
152 | NewFileName expresses an actual rename/move
|
---|
153 | request.
|
---|
154 |
|
---|
155 | @retval EFI_ACCESS_DENIED VirtioFsFile is the (possibly indirect) parent
|
---|
156 | directory of at least one other VIRTIO_FS_FILE
|
---|
157 | that is open for the same Virtio Filesystem
|
---|
158 | (identified by VirtioFsFile->OwnerFs). Renaming
|
---|
159 | VirtioFsFile would invalidate the canonical
|
---|
160 | pathnames of those VIRTIO_FS_FILE instances;
|
---|
161 | therefore the request has been rejected.
|
---|
162 |
|
---|
163 | @retval EFI_ACCESS_DENIED VirtioFsFile is not open for writing, but
|
---|
164 | NewFileName expresses an actual rename/move
|
---|
165 | request.
|
---|
166 |
|
---|
167 | @retval EFI_NOT_FOUND At least one dot-dot component in NewFileName
|
---|
168 | attempted to escape the root directory.
|
---|
169 |
|
---|
170 | @return Error codes propagated from underlying functions.
|
---|
171 | **/
|
---|
172 | STATIC
|
---|
173 | EFI_STATUS
|
---|
174 | Rename (
|
---|
175 | IN OUT VIRTIO_FS_FILE *VirtioFsFile,
|
---|
176 | IN CHAR16 *NewFileName
|
---|
177 | )
|
---|
178 | {
|
---|
179 |
|
---|
180 | VIRTIO_FS *VirtioFs;
|
---|
181 | EFI_STATUS Status;
|
---|
182 | CHAR8 *Destination;
|
---|
183 | BOOLEAN RootEscape;
|
---|
184 | UINT64 OldParentDirNodeId;
|
---|
185 | CHAR8 *OldLastComponent;
|
---|
186 | UINT64 NewParentDirNodeId;
|
---|
187 | CHAR8 *NewLastComponent;
|
---|
188 |
|
---|
189 | VirtioFs = VirtioFsFile->OwnerFs;
|
---|
190 |
|
---|
191 | //
|
---|
192 | // The root directory cannot be renamed.
|
---|
193 | //
|
---|
194 | if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, "/") == 0) {
|
---|
195 | if (StrCmp (NewFileName, L"") == 0) {
|
---|
196 | //
|
---|
197 | // Not a rename request anyway.
|
---|
198 | //
|
---|
199 | return EFI_SUCCESS;
|
---|
200 | }
|
---|
201 | return EFI_ACCESS_DENIED;
|
---|
202 | }
|
---|
203 |
|
---|
204 | //
|
---|
205 | // Compose the canonical pathname for the destination.
|
---|
206 | //
|
---|
207 | Status = VirtioFsComposeRenameDestination (VirtioFsFile->CanonicalPathname,
|
---|
208 | NewFileName, &Destination, &RootEscape);
|
---|
209 | if (EFI_ERROR (Status)) {
|
---|
210 | return Status;
|
---|
211 | }
|
---|
212 | if (RootEscape) {
|
---|
213 | Status = EFI_NOT_FOUND;
|
---|
214 | goto FreeDestination;
|
---|
215 | }
|
---|
216 | //
|
---|
217 | // If the rename would leave VirtioFsFile->CanonicalPathname unchanged, then
|
---|
218 | // EFI_FILE_PROTOCOL.SetInfo() isn't asking for a rename actually.
|
---|
219 | //
|
---|
220 | if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, Destination) == 0) {
|
---|
221 | Status = EFI_SUCCESS;
|
---|
222 | goto FreeDestination;
|
---|
223 | }
|
---|
224 | //
|
---|
225 | // Check if the rename would break the canonical pathnames of other
|
---|
226 | // VIRTIO_FS_FILE instances of the same VIRTIO_FS.
|
---|
227 | //
|
---|
228 | if (VirtioFsFile->IsDirectory) {
|
---|
229 | UINTN PathLen;
|
---|
230 | LIST_ENTRY *OpenFilesEntry;
|
---|
231 |
|
---|
232 | PathLen = AsciiStrLen (VirtioFsFile->CanonicalPathname);
|
---|
233 | BASE_LIST_FOR_EACH (OpenFilesEntry, &VirtioFs->OpenFiles) {
|
---|
234 | VIRTIO_FS_FILE *OtherFile;
|
---|
235 |
|
---|
236 | OtherFile = VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY (OpenFilesEntry);
|
---|
237 | if (OtherFile != VirtioFsFile &&
|
---|
238 | AsciiStrnCmp (VirtioFsFile->CanonicalPathname,
|
---|
239 | OtherFile->CanonicalPathname, PathLen) == 0 &&
|
---|
240 | (OtherFile->CanonicalPathname[PathLen] == '\0' ||
|
---|
241 | OtherFile->CanonicalPathname[PathLen] == '/')) {
|
---|
242 | //
|
---|
243 | // OtherFile refers to the same directory as VirtioFsFile, or is a
|
---|
244 | // (possibly indirect) child of the directory referred to by
|
---|
245 | // VirtioFsFile.
|
---|
246 | //
|
---|
247 | Status = EFI_ACCESS_DENIED;
|
---|
248 | goto FreeDestination;
|
---|
249 | }
|
---|
250 | }
|
---|
251 | }
|
---|
252 | //
|
---|
253 | // From this point on, the file needs to be open for writing.
|
---|
254 | //
|
---|
255 | if (!VirtioFsFile->IsOpenForWriting) {
|
---|
256 | Status = EFI_ACCESS_DENIED;
|
---|
257 | goto FreeDestination;
|
---|
258 | }
|
---|
259 | //
|
---|
260 | // Split both source and destination canonical pathnames into (most specific
|
---|
261 | // parent directory, last component) pairs.
|
---|
262 | //
|
---|
263 | Status = VirtioFsLookupMostSpecificParentDir (VirtioFs,
|
---|
264 | VirtioFsFile->CanonicalPathname, &OldParentDirNodeId,
|
---|
265 | &OldLastComponent);
|
---|
266 | if (EFI_ERROR (Status)) {
|
---|
267 | goto FreeDestination;
|
---|
268 | }
|
---|
269 | Status = VirtioFsLookupMostSpecificParentDir (VirtioFs, Destination,
|
---|
270 | &NewParentDirNodeId, &NewLastComponent);
|
---|
271 | if (EFI_ERROR (Status)) {
|
---|
272 | goto ForgetOldParentDirNodeId;
|
---|
273 | }
|
---|
274 | //
|
---|
275 | // Perform the rename. If the destination path exists, the rename will fail.
|
---|
276 | //
|
---|
277 | Status = VirtioFsFuseRename (VirtioFs, OldParentDirNodeId, OldLastComponent,
|
---|
278 | NewParentDirNodeId, NewLastComponent);
|
---|
279 | if (EFI_ERROR (Status)) {
|
---|
280 | goto ForgetNewParentDirNodeId;
|
---|
281 | }
|
---|
282 |
|
---|
283 | //
|
---|
284 | // Swap in the new canonical pathname.
|
---|
285 | //
|
---|
286 | FreePool (VirtioFsFile->CanonicalPathname);
|
---|
287 | VirtioFsFile->CanonicalPathname = Destination;
|
---|
288 | Destination = NULL;
|
---|
289 | Status = EFI_SUCCESS;
|
---|
290 |
|
---|
291 | //
|
---|
292 | // Fall through.
|
---|
293 | //
|
---|
294 | ForgetNewParentDirNodeId:
|
---|
295 | if (NewParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
|
---|
296 | VirtioFsFuseForget (VirtioFs, NewParentDirNodeId);
|
---|
297 | }
|
---|
298 |
|
---|
299 | ForgetOldParentDirNodeId:
|
---|
300 | if (OldParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
|
---|
301 | VirtioFsFuseForget (VirtioFs, OldParentDirNodeId);
|
---|
302 | }
|
---|
303 |
|
---|
304 | FreeDestination:
|
---|
305 | if (Destination != NULL) {
|
---|
306 | FreePool (Destination);
|
---|
307 | }
|
---|
308 | return Status;
|
---|
309 | }
|
---|
310 |
|
---|
311 | /**
|
---|
312 | Update the attributes of a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.
|
---|
313 |
|
---|
314 | @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to update the attributes of.
|
---|
315 |
|
---|
316 | @param[in] NewFileInfo The new attributes requested by
|
---|
317 | EFI_FILE_PROTOCOL.SetInfo(). NewFileInfo->Size
|
---|
318 | and NewFileInfo->FileName are ignored.
|
---|
319 |
|
---|
320 | @retval EFI_SUCCESS No attributes had to be updated.
|
---|
321 |
|
---|
322 | @retval EFI_SUCCESS The required set of attribute updates has been
|
---|
323 | determined and performed successfully.
|
---|
324 |
|
---|
325 | @retval EFI_ACCESS_DENIED NewFileInfo requests an update to a property
|
---|
326 | different from the EFI_FILE_READ_ONLY bit in the
|
---|
327 | Attribute field, but VirtioFsFile is not open for
|
---|
328 | writing.
|
---|
329 |
|
---|
330 | @return Error codes propagated from underlying functions.
|
---|
331 | **/
|
---|
332 | STATIC
|
---|
333 | EFI_STATUS
|
---|
334 | UpdateAttributes (
|
---|
335 | IN OUT VIRTIO_FS_FILE *VirtioFsFile,
|
---|
336 | IN EFI_FILE_INFO *NewFileInfo
|
---|
337 | )
|
---|
338 | {
|
---|
339 | VIRTIO_FS *VirtioFs;
|
---|
340 | EFI_STATUS Status;
|
---|
341 | VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
|
---|
342 | EFI_FILE_INFO FileInfo;
|
---|
343 | BOOLEAN UpdateFileSize;
|
---|
344 | UINT64 FileSize;
|
---|
345 | BOOLEAN UpdateAtime;
|
---|
346 | BOOLEAN UpdateMtime;
|
---|
347 | UINT64 Atime;
|
---|
348 | UINT64 Mtime;
|
---|
349 | BOOLEAN UpdateMode;
|
---|
350 | UINT32 Mode;
|
---|
351 |
|
---|
352 | VirtioFs = VirtioFsFile->OwnerFs;
|
---|
353 |
|
---|
354 | //
|
---|
355 | // Fetch the current attributes first, so we can build the difference between
|
---|
356 | // them and NewFileInfo.
|
---|
357 | //
|
---|
358 | Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
|
---|
359 | if (EFI_ERROR (Status)) {
|
---|
360 | return Status;
|
---|
361 | }
|
---|
362 | Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
|
---|
363 | if (EFI_ERROR (Status)) {
|
---|
364 | return Status;
|
---|
365 | }
|
---|
366 | //
|
---|
367 | // Collect the updates.
|
---|
368 | //
|
---|
369 | if (VirtioFsFile->IsDirectory) {
|
---|
370 | UpdateFileSize = FALSE;
|
---|
371 | } else {
|
---|
372 | VirtioFsGetFuseSizeUpdate (&FileInfo, NewFileInfo, &UpdateFileSize,
|
---|
373 | &FileSize);
|
---|
374 | }
|
---|
375 |
|
---|
376 | Status = VirtioFsGetFuseTimeUpdates (&FileInfo, NewFileInfo, &UpdateAtime,
|
---|
377 | &UpdateMtime, &Atime, &Mtime);
|
---|
378 | if (EFI_ERROR (Status)) {
|
---|
379 | return Status;
|
---|
380 | }
|
---|
381 |
|
---|
382 | Status = VirtioFsGetFuseModeUpdate (&FileInfo, NewFileInfo, &UpdateMode,
|
---|
383 | &Mode);
|
---|
384 | if (EFI_ERROR (Status)) {
|
---|
385 | return Status;
|
---|
386 | }
|
---|
387 |
|
---|
388 | //
|
---|
389 | // If no attribute updates are necessary, we're done.
|
---|
390 | //
|
---|
391 | if (!UpdateFileSize && !UpdateAtime && !UpdateMtime && !UpdateMode) {
|
---|
392 | return EFI_SUCCESS;
|
---|
393 | }
|
---|
394 | //
|
---|
395 | // If the file is not open for writing, then only Mode may be updated (for
|
---|
396 | // toggling EFI_FILE_READ_ONLY).
|
---|
397 | //
|
---|
398 | if (!VirtioFsFile->IsOpenForWriting &&
|
---|
399 | (UpdateFileSize || UpdateAtime || UpdateMtime)) {
|
---|
400 | return EFI_ACCESS_DENIED;
|
---|
401 | }
|
---|
402 | //
|
---|
403 | // Send the FUSE_SETATTR request now.
|
---|
404 | //
|
---|
405 | Status = VirtioFsFuseSetAttr (
|
---|
406 | VirtioFs,
|
---|
407 | VirtioFsFile->NodeId,
|
---|
408 | UpdateFileSize ? &FileSize : NULL,
|
---|
409 | UpdateAtime ? &Atime : NULL,
|
---|
410 | UpdateMtime ? &Mtime : NULL,
|
---|
411 | UpdateMode ? &Mode : NULL
|
---|
412 | );
|
---|
413 | return Status;
|
---|
414 | }
|
---|
415 |
|
---|
416 | /**
|
---|
417 | Process an EFI_FILE_INFO setting request.
|
---|
418 | **/
|
---|
419 | STATIC
|
---|
420 | EFI_STATUS
|
---|
421 | SetFileInfo (
|
---|
422 | IN EFI_FILE_PROTOCOL *This,
|
---|
423 | IN UINTN BufferSize,
|
---|
424 | IN VOID *Buffer
|
---|
425 | )
|
---|
426 | {
|
---|
427 | VIRTIO_FS_FILE *VirtioFsFile;
|
---|
428 | EFI_STATUS Status;
|
---|
429 | EFI_FILE_INFO *FileInfo;
|
---|
430 |
|
---|
431 | VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
|
---|
432 |
|
---|
433 | //
|
---|
434 | // Validate if Buffer passes as EFI_FILE_INFO.
|
---|
435 | //
|
---|
436 | Status = ValidateInfoStructure (
|
---|
437 | BufferSize, // SizeByProtocolCaller
|
---|
438 | OFFSET_OF (EFI_FILE_INFO,
|
---|
439 | FileName) + sizeof (CHAR16), // MinimumStructSize
|
---|
440 | TRUE, // IsSizeByInfoPresent
|
---|
441 | Buffer
|
---|
442 | );
|
---|
443 | if (EFI_ERROR (Status)) {
|
---|
444 | return Status;
|
---|
445 | }
|
---|
446 | FileInfo = Buffer;
|
---|
447 |
|
---|
448 | //
|
---|
449 | // Perform the rename/move request, if any.
|
---|
450 | //
|
---|
451 | Status = Rename (VirtioFsFile, FileInfo->FileName);
|
---|
452 | if (EFI_ERROR (Status)) {
|
---|
453 | return Status;
|
---|
454 | }
|
---|
455 | //
|
---|
456 | // Update any attributes requested.
|
---|
457 | //
|
---|
458 | Status = UpdateAttributes (VirtioFsFile, FileInfo);
|
---|
459 | //
|
---|
460 | // The UEFI spec does not speak about partial failure in
|
---|
461 | // EFI_FILE_PROTOCOL.SetInfo(); we won't try to roll back the rename (if
|
---|
462 | // there was one) in case the attribute updates fail.
|
---|
463 | //
|
---|
464 | return Status;
|
---|
465 | }
|
---|
466 |
|
---|
467 | /**
|
---|
468 | Process an EFI_FILE_SYSTEM_INFO setting request.
|
---|
469 | **/
|
---|
470 | STATIC
|
---|
471 | EFI_STATUS
|
---|
472 | SetFileSystemInfo (
|
---|
473 | IN EFI_FILE_PROTOCOL *This,
|
---|
474 | IN UINTN BufferSize,
|
---|
475 | IN VOID *Buffer
|
---|
476 | )
|
---|
477 | {
|
---|
478 | VIRTIO_FS_FILE *VirtioFsFile;
|
---|
479 | VIRTIO_FS *VirtioFs;
|
---|
480 | EFI_STATUS Status;
|
---|
481 | EFI_FILE_SYSTEM_INFO *FileSystemInfo;
|
---|
482 |
|
---|
483 | VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
|
---|
484 | VirtioFs = VirtioFsFile->OwnerFs;
|
---|
485 |
|
---|
486 | //
|
---|
487 | // Validate if Buffer passes as EFI_FILE_SYSTEM_INFO.
|
---|
488 | //
|
---|
489 | Status = ValidateInfoStructure (
|
---|
490 | BufferSize, // SizeByProtocolCaller
|
---|
491 | OFFSET_OF (EFI_FILE_SYSTEM_INFO,
|
---|
492 | VolumeLabel) + sizeof (CHAR16), // MinimumStructSize
|
---|
493 | TRUE, // IsSizeByInfoPresent
|
---|
494 | Buffer
|
---|
495 | );
|
---|
496 | if (EFI_ERROR (Status)) {
|
---|
497 | return Status;
|
---|
498 | }
|
---|
499 | FileSystemInfo = Buffer;
|
---|
500 |
|
---|
501 | //
|
---|
502 | // EFI_FILE_SYSTEM_INFO fields other than VolumeLabel cannot be changed, per
|
---|
503 | // spec.
|
---|
504 | //
|
---|
505 | // If the label is being changed to its current value, report success;
|
---|
506 | // otherwise, reject the request, as the Virtio Filesystem device does not
|
---|
507 | // support changing the label.
|
---|
508 | //
|
---|
509 | if (StrCmp (FileSystemInfo->VolumeLabel, VirtioFs->Label) == 0) {
|
---|
510 | return EFI_SUCCESS;
|
---|
511 | }
|
---|
512 | return EFI_WRITE_PROTECTED;
|
---|
513 | }
|
---|
514 |
|
---|
515 | /**
|
---|
516 | Process an EFI_FILE_SYSTEM_VOLUME_LABEL setting request.
|
---|
517 | **/
|
---|
518 | STATIC
|
---|
519 | EFI_STATUS
|
---|
520 | SetFileSystemVolumeLabelInfo (
|
---|
521 | IN EFI_FILE_PROTOCOL *This,
|
---|
522 | IN UINTN BufferSize,
|
---|
523 | IN VOID *Buffer
|
---|
524 | )
|
---|
525 | {
|
---|
526 | VIRTIO_FS_FILE *VirtioFsFile;
|
---|
527 | VIRTIO_FS *VirtioFs;
|
---|
528 | EFI_STATUS Status;
|
---|
529 | EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;
|
---|
530 |
|
---|
531 | VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
|
---|
532 | VirtioFs = VirtioFsFile->OwnerFs;
|
---|
533 |
|
---|
534 | //
|
---|
535 | // Validate if Buffer passes as EFI_FILE_SYSTEM_VOLUME_LABEL.
|
---|
536 | //
|
---|
537 | Status = ValidateInfoStructure (
|
---|
538 | BufferSize, // SizeByProtocolCaller
|
---|
539 | OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL,
|
---|
540 | VolumeLabel) + sizeof (CHAR16), // MinimumStructSize
|
---|
541 | FALSE, // IsSizeByInfoPresent
|
---|
542 | Buffer
|
---|
543 | );
|
---|
544 | if (EFI_ERROR (Status)) {
|
---|
545 | return Status;
|
---|
546 | }
|
---|
547 | FileSystemVolumeLabel = Buffer;
|
---|
548 |
|
---|
549 | //
|
---|
550 | // If the label is being changed to its current value, report success;
|
---|
551 | // otherwise, reject the request, as the Virtio Filesystem device does not
|
---|
552 | // support changing the label.
|
---|
553 | //
|
---|
554 | if (StrCmp (FileSystemVolumeLabel->VolumeLabel, VirtioFs->Label) == 0) {
|
---|
555 | return EFI_SUCCESS;
|
---|
556 | }
|
---|
557 | return EFI_WRITE_PROTECTED;
|
---|
558 | }
|
---|
559 |
|
---|
560 | EFI_STATUS
|
---|
561 | EFIAPI
|
---|
562 | VirtioFsSimpleFileSetInfo (
|
---|
563 | IN EFI_FILE_PROTOCOL *This,
|
---|
564 | IN EFI_GUID *InformationType,
|
---|
565 | IN UINTN BufferSize,
|
---|
566 | IN VOID *Buffer
|
---|
567 | )
|
---|
568 | {
|
---|
569 | if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
|
---|
570 | return SetFileInfo (This, BufferSize, Buffer);
|
---|
571 | }
|
---|
572 |
|
---|
573 | if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
|
---|
574 | return SetFileSystemInfo (This, BufferSize, Buffer);
|
---|
575 | }
|
---|
576 |
|
---|
577 | if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
|
---|
578 | return SetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);
|
---|
579 | }
|
---|
580 |
|
---|
581 | return EFI_UNSUPPORTED;
|
---|
582 | }
|
---|