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