]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/VirtioFsDxe/SimpleFsOpen.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioFsDxe / SimpleFsOpen.c
CommitLineData
334c13e1
LE
1/** @file\r
2 EFI_FILE_PROTOCOL.Open() 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
de0e1190
LE
9#include <Library/BaseLib.h> // AsciiStrCmp()\r
10#include <Library/MemoryAllocationLib.h> // AllocatePool()\r
11\r
334c13e1
LE
12#include "VirtioFsDxe.h"\r
13\r
de0e1190
LE
14/**\r
15 Open the root directory, possibly for writing.\r
16\r
17 @param[in,out] VirtioFs The Virtio Filesystem device whose root directory\r
18 should be opened.\r
19\r
20 @param[out] NewHandle The new EFI_FILE_PROTOCOL instance through which\r
21 the root directory can be accessed.\r
22\r
23 @param[in] OpenForWriting TRUE if the root directory should be opened for\r
24 read-write access. FALSE if the root directory\r
25 should be opened for read-only access. Opening the\r
26 root directory for read-write access is useful for\r
27 calling EFI_FILE_PROTOCOL.Flush() or\r
28 EFI_FILE_PROTOCOL.SetInfo() later, for syncing or\r
29 touching the root directory, respectively.\r
30\r
31 @retval EFI_SUCCESS The root directory has been opened successfully.\r
32\r
33 @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the root directory is\r
34 marked as read-only.\r
35\r
36 @return Error codes propagated from underlying functions.\r
37**/\r
38STATIC\r
39EFI_STATUS\r
40OpenRootDirectory (\r
ac0a286f
MK
41 IN OUT VIRTIO_FS *VirtioFs,\r
42 OUT EFI_FILE_PROTOCOL **NewHandle,\r
43 IN BOOLEAN OpenForWriting\r
de0e1190
LE
44 )\r
45{\r
ac0a286f
MK
46 EFI_STATUS Status;\r
47 VIRTIO_FS_FILE *NewVirtioFsFile;\r
de0e1190
LE
48\r
49 //\r
50 // VirtioFsOpenVolume() opens the root directory for read-only access. If the\r
51 // current request is to open the root directory for read-write access, so\r
52 // that EFI_FILE_PROTOCOL.Flush() or EFI_FILE_PROTOCOL.SetInfo()+timestamps\r
53 // can be used on the root directory later, then we have to check for write\r
54 // permission first.\r
55 //\r
56 if (OpenForWriting) {\r
ac0a286f
MK
57 VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
58 EFI_FILE_INFO FileInfo;\r
59\r
60 Status = VirtioFsFuseGetAttr (\r
61 VirtioFs,\r
62 VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID,\r
63 &FuseAttr\r
64 );\r
de0e1190
LE
65 if (EFI_ERROR (Status)) {\r
66 return Status;\r
67 }\r
ac0a286f 68\r
de0e1190
LE
69 Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r
70 if (EFI_ERROR (Status)) {\r
71 return Status;\r
72 }\r
ac0a286f 73\r
de0e1190
LE
74 if ((FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0) {\r
75 return EFI_ACCESS_DENIED;\r
76 }\r
77 }\r
78\r
79 Status = VirtioFsOpenVolume (&VirtioFs->SimpleFs, NewHandle);\r
80 if (EFI_ERROR (Status)) {\r
81 return Status;\r
82 }\r
83\r
ac0a286f 84 NewVirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (*NewHandle);\r
de0e1190
LE
85 NewVirtioFsFile->IsOpenForWriting = OpenForWriting;\r
86 return EFI_SUCCESS;\r
87}\r
88\r
89/**\r
90 Open an existent regular file or non-root directory.\r
91\r
92 @param[in,out] VirtioFs The Virtio Filesystem device on which the\r
93 regular file or directory should be opened.\r
94\r
95 @param[in] DirNodeId The inode number of the immediate parent\r
96 directory of the regular file or directory to\r
97 open.\r
98\r
99 @param[in] Name The single-component filename of the regular\r
100 file or directory to open, under the immediate\r
101 parent directory identified by DirNodeId.\r
102\r
103 @param[in] OpenForWriting TRUE if the regular file or directory should be\r
104 opened for read-write access. FALSE if the\r
105 regular file or directory should be opened for\r
106 read-only access. Opening a directory for\r
107 read-write access is useful for deleting,\r
108 renaming, syncing or touching the directory\r
109 later.\r
110\r
111 @param[out] NodeId The inode number of the regular file or\r
112 directory, returned by the Virtio Filesystem\r
113 device.\r
114\r
115 @param[out] FuseHandle The open handle to the regular file or\r
116 directory, returned by the Virtio Filesystem\r
117 device.\r
118\r
119 @param[out] NodeIsDirectory Set to TRUE on output if Name was found to refer\r
120 to a directory. Set to FALSE if Name was found\r
121 to refer to a regular file.\r
122\r
123 @retval EFI_SUCCESS The regular file or directory has been looked up\r
124 and opened successfully.\r
125\r
126 @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the regular file or\r
127 directory is marked read-only.\r
128\r
129 @retval EFI_NOT_FOUND A directory entry called Name was not found in the\r
130 directory identified by DirNodeId. (EFI_NOT_FOUND\r
131 is not returned for any other condition.)\r
132\r
133 @return Errors propagated from underlying functions. If\r
134 the error code to propagate were EFI_NOT_FOUND, it\r
135 is remapped to EFI_DEVICE_ERROR.\r
136**/\r
137STATIC\r
138EFI_STATUS\r
139OpenExistentFileOrDirectory (\r
ac0a286f
MK
140 IN OUT VIRTIO_FS *VirtioFs,\r
141 IN UINT64 DirNodeId,\r
142 IN CHAR8 *Name,\r
143 IN BOOLEAN OpenForWriting,\r
144 OUT UINT64 *NodeId,\r
145 OUT UINT64 *FuseHandle,\r
146 OUT BOOLEAN *NodeIsDirectory\r
de0e1190
LE
147 )\r
148{\r
ac0a286f
MK
149 EFI_STATUS Status;\r
150 UINT64 ResolvedNodeId;\r
151 VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
152 EFI_FILE_INFO FileInfo;\r
153 BOOLEAN IsDirectory;\r
154 UINT64 NewFuseHandle;\r
155\r
156 Status = VirtioFsFuseLookup (\r
157 VirtioFs,\r
158 DirNodeId,\r
159 Name,\r
160 &ResolvedNodeId,\r
161 &FuseAttr\r
162 );\r
de0e1190
LE
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
ac0a286f 166\r
de0e1190
LE
167 Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r
168 if (EFI_ERROR (Status)) {\r
169 goto ForgetResolvedNodeId;\r
170 }\r
171\r
ac0a286f 172 if (OpenForWriting && ((FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0)) {\r
de0e1190
LE
173 Status = EFI_ACCESS_DENIED;\r
174 goto ForgetResolvedNodeId;\r
175 }\r
176\r
177 IsDirectory = (BOOLEAN)((FileInfo.Attribute & EFI_FILE_DIRECTORY) != 0);\r
178 if (IsDirectory) {\r
179 //\r
180 // If OpenForWriting is TRUE here, that's not passed to\r
181 // VirtioFsFuseOpenDir(); it does not affect the FUSE_OPENDIR request we\r
182 // send. OpenForWriting=TRUE will only permit attempts to delete, rename,\r
183 // flush (sync), and touch the directory.\r
184 //\r
185 Status = VirtioFsFuseOpenDir (VirtioFs, ResolvedNodeId, &NewFuseHandle);\r
186 } else {\r
ac0a286f
MK
187 Status = VirtioFsFuseOpen (\r
188 VirtioFs,\r
189 ResolvedNodeId,\r
190 OpenForWriting,\r
191 &NewFuseHandle\r
192 );\r
de0e1190 193 }\r
ac0a286f 194\r
de0e1190
LE
195 if (EFI_ERROR (Status)) {\r
196 goto ForgetResolvedNodeId;\r
197 }\r
198\r
199 *NodeId = ResolvedNodeId;\r
200 *FuseHandle = NewFuseHandle;\r
201 *NodeIsDirectory = IsDirectory;\r
202 return EFI_SUCCESS;\r
203\r
204ForgetResolvedNodeId:\r
205 VirtioFsFuseForget (VirtioFs, ResolvedNodeId);\r
206 return (Status == EFI_NOT_FOUND) ? EFI_DEVICE_ERROR : Status;\r
207}\r
208\r
209/**\r
210 Create a directory.\r
211\r
212 @param[in,out] VirtioFs The Virtio Filesystem device on which the directory\r
213 should be created.\r
214\r
215 @param[in] DirNodeId The inode number of the immediate parent directory\r
216 of the directory to create.\r
217\r
218 @param[in] Name The single-component filename of the directory to\r
219 create, under the immediate parent directory\r
220 identified by DirNodeId.\r
221\r
222 @param[out] NodeId The inode number of the directory created, returned\r
223 by the Virtio Filesystem device.\r
224\r
225 @param[out] FuseHandle The open handle to the directory created, returned\r
226 by the Virtio Filesystem device.\r
227\r
228 @retval EFI_SUCCESS The directory has been created successfully.\r
229\r
230 @return Errors propagated from underlying functions.\r
231**/\r
232STATIC\r
233EFI_STATUS\r
234CreateDirectory (\r
ac0a286f
MK
235 IN OUT VIRTIO_FS *VirtioFs,\r
236 IN UINT64 DirNodeId,\r
237 IN CHAR8 *Name,\r
238 OUT UINT64 *NodeId,\r
239 OUT UINT64 *FuseHandle\r
de0e1190
LE
240 )\r
241{\r
ac0a286f
MK
242 EFI_STATUS Status;\r
243 UINT64 NewChildDirNodeId;\r
244 UINT64 NewFuseHandle;\r
de0e1190
LE
245\r
246 Status = VirtioFsFuseMkDir (VirtioFs, DirNodeId, Name, &NewChildDirNodeId);\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
250\r
251 Status = VirtioFsFuseOpenDir (VirtioFs, NewChildDirNodeId, &NewFuseHandle);\r
252 if (EFI_ERROR (Status)) {\r
253 goto RemoveNewChildDir;\r
254 }\r
255\r
256 *NodeId = NewChildDirNodeId;\r
257 *FuseHandle = NewFuseHandle;\r
258 return EFI_SUCCESS;\r
259\r
260RemoveNewChildDir:\r
261 VirtioFsFuseRemoveFileOrDir (VirtioFs, DirNodeId, Name, TRUE /* IsDir */);\r
262 VirtioFsFuseForget (VirtioFs, NewChildDirNodeId);\r
263 return Status;\r
264}\r
265\r
266/**\r
267 Create a regular file.\r
268\r
269 @param[in,out] VirtioFs The Virtio Filesystem device on which the regular\r
270 file should be created.\r
271\r
272 @param[in] DirNodeId The inode number of the immediate parent directory\r
273 of the regular file to create.\r
274\r
275 @param[in] Name The single-component filename of the regular file to\r
276 create, under the immediate parent directory\r
277 identified by DirNodeId.\r
278\r
279 @param[out] NodeId The inode number of the regular file created,\r
280 returned by the Virtio Filesystem device.\r
281\r
282 @param[out] FuseHandle The open handle to the regular file created,\r
283 returned by the Virtio Filesystem device.\r
284\r
285 @retval EFI_SUCCESS The regular file has been created successfully.\r
286\r
287 @return Errors propagated from underlying functions.\r
288**/\r
289STATIC\r
290EFI_STATUS\r
291CreateRegularFile (\r
ac0a286f
MK
292 IN OUT VIRTIO_FS *VirtioFs,\r
293 IN UINT64 DirNodeId,\r
294 IN CHAR8 *Name,\r
295 OUT UINT64 *NodeId,\r
296 OUT UINT64 *FuseHandle\r
de0e1190
LE
297 )\r
298{\r
ac0a286f
MK
299 return VirtioFsFuseOpenOrCreate (\r
300 VirtioFs,\r
301 DirNodeId,\r
302 Name,\r
303 NodeId,\r
304 FuseHandle\r
305 );\r
de0e1190
LE
306}\r
307\r
334c13e1
LE
308EFI_STATUS\r
309EFIAPI\r
310VirtioFsSimpleFileOpen (\r
ac0a286f
MK
311 IN EFI_FILE_PROTOCOL *This,\r
312 OUT EFI_FILE_PROTOCOL **NewHandle,\r
313 IN CHAR16 *FileName,\r
314 IN UINT64 OpenMode,\r
315 IN UINT64 Attributes\r
334c13e1
LE
316 )\r
317{\r
ac0a286f
MK
318 VIRTIO_FS_FILE *VirtioFsFile;\r
319 VIRTIO_FS *VirtioFs;\r
320 BOOLEAN OpenForWriting;\r
321 BOOLEAN PermitCreation;\r
322 BOOLEAN CreateDirectoryIfCreating;\r
323 VIRTIO_FS_FILE *NewVirtioFsFile;\r
324 EFI_STATUS Status;\r
325 CHAR8 *NewCanonicalPath;\r
326 BOOLEAN RootEscape;\r
327 UINT64 DirNodeId;\r
328 CHAR8 *LastComponent;\r
329 UINT64 NewNodeId;\r
330 UINT64 NewFuseHandle;\r
331 BOOLEAN NewNodeIsDirectory;\r
de0e1190
LE
332\r
333 VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r
334 VirtioFs = VirtioFsFile->OwnerFs;\r
335\r
336 //\r
337 // Validate OpenMode.\r
338 //\r
339 switch (OpenMode) {\r
ac0a286f
MK
340 case EFI_FILE_MODE_READ:\r
341 OpenForWriting = FALSE;\r
342 PermitCreation = FALSE;\r
343 break;\r
344 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
345 OpenForWriting = TRUE;\r
346 PermitCreation = FALSE;\r
347 break;\r
348 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r
349 OpenForWriting = TRUE;\r
350 PermitCreation = TRUE;\r
351 break;\r
352 default:\r
353 return EFI_INVALID_PARAMETER;\r
de0e1190
LE
354 }\r
355\r
d82c4693
SD
356 //\r
357 // Set CreateDirectoryIfCreating to suppress incorrect compiler/analyzer\r
358 // warnings.\r
359 //\r
360 CreateDirectoryIfCreating = FALSE;\r
361\r
de0e1190
LE
362 //\r
363 // Validate the Attributes requested for the case when the file ends up being\r
364 // created, provided creation is permitted.\r
365 //\r
366 if (PermitCreation) {\r
367 if ((Attributes & ~EFI_FILE_VALID_ATTR) != 0) {\r
368 //\r
369 // Unknown attribute requested.\r
370 //\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
373\r
374 ASSERT (OpenForWriting);\r
375 if ((Attributes & EFI_FILE_READ_ONLY) != 0) {\r
376 DEBUG ((\r
377 DEBUG_ERROR,\r
378 ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\" "\r
379 "OpenMode=0x%Lx Attributes=0x%Lx: nonsensical request to possibly "\r
380 "create a file marked read-only, for read-write access\n"),\r
381 __FUNCTION__,\r
382 VirtioFs->Label,\r
383 VirtioFsFile->CanonicalPathname,\r
384 FileName,\r
385 OpenMode,\r
386 Attributes\r
387 ));\r
388 return EFI_INVALID_PARAMETER;\r
389 }\r
ac0a286f 390\r
de0e1190
LE
391 CreateDirectoryIfCreating = (BOOLEAN)((Attributes &\r
392 EFI_FILE_DIRECTORY) != 0);\r
393 }\r
394\r
395 //\r
396 // Referring to a file relative to a regular file makes no sense (or at least\r
397 // it cannot be implemented consistently with how a file is referred to\r
398 // relative to a directory).\r
399 //\r
400 if (!VirtioFsFile->IsDirectory) {\r
401 DEBUG ((\r
402 DEBUG_ERROR,\r
403 ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\": "\r
404 "nonsensical request to open a file or directory relative to a regular "\r
405 "file\n"),\r
406 __FUNCTION__,\r
407 VirtioFs->Label,\r
408 VirtioFsFile->CanonicalPathname,\r
409 FileName\r
410 ));\r
411 return EFI_INVALID_PARAMETER;\r
412 }\r
413\r
414 //\r
415 // Allocate the new VIRTIO_FS_FILE object.\r
416 //\r
417 NewVirtioFsFile = AllocatePool (sizeof *NewVirtioFsFile);\r
418 if (NewVirtioFsFile == NULL) {\r
419 return EFI_OUT_OF_RESOURCES;\r
420 }\r
421\r
422 //\r
423 // Create the canonical pathname at which the desired file is expected to\r
424 // exist.\r
425 //\r
ac0a286f
MK
426 Status = VirtioFsAppendPath (\r
427 VirtioFsFile->CanonicalPathname,\r
428 FileName,\r
429 &NewCanonicalPath,\r
430 &RootEscape\r
431 );\r
de0e1190
LE
432 if (EFI_ERROR (Status)) {\r
433 goto FreeNewVirtioFsFile;\r
434 }\r
ac0a286f 435\r
de0e1190
LE
436 if (RootEscape) {\r
437 Status = EFI_ACCESS_DENIED;\r
438 goto FreeNewCanonicalPath;\r
439 }\r
440\r
441 //\r
442 // If the desired file is the root directory, just open the volume one more\r
443 // time, without looking up anything.\r
444 //\r
445 if (AsciiStrCmp (NewCanonicalPath, "/") == 0) {\r
446 FreePool (NewCanonicalPath);\r
447 FreePool (NewVirtioFsFile);\r
448 return OpenRootDirectory (VirtioFs, NewHandle, OpenForWriting);\r
449 }\r
450\r
451 //\r
452 // Split the new canonical pathname into most specific parent directory\r
453 // (given by DirNodeId) and last pathname component (i.e., immediate child\r
454 // within that parent directory).\r
455 //\r
ac0a286f
MK
456 Status = VirtioFsLookupMostSpecificParentDir (\r
457 VirtioFs,\r
458 NewCanonicalPath,\r
459 &DirNodeId,\r
460 &LastComponent\r
461 );\r
de0e1190
LE
462 if (EFI_ERROR (Status)) {\r
463 goto FreeNewCanonicalPath;\r
464 }\r
465\r
d82c4693
SD
466 //\r
467 // Set NewNodeIsDirectory to suppress incorrect compiler/analyzer warnings.\r
468 //\r
469 NewNodeIsDirectory = FALSE;\r
470\r
de0e1190
LE
471 //\r
472 // Try to open LastComponent directly under DirNodeId, as an existent regular\r
473 // file or directory.\r
474 //\r
ac0a286f
MK
475 Status = OpenExistentFileOrDirectory (\r
476 VirtioFs,\r
477 DirNodeId,\r
478 LastComponent,\r
479 OpenForWriting,\r
480 &NewNodeId,\r
481 &NewFuseHandle,\r
482 &NewNodeIsDirectory\r
483 );\r
de0e1190
LE
484 //\r
485 // If LastComponent could not be found under DirNodeId, but the request\r
486 // allows us to create a new entry, attempt creating the requested regular\r
487 // file or directory.\r
488 //\r
ac0a286f 489 if ((Status == EFI_NOT_FOUND) && PermitCreation) {\r
de0e1190
LE
490 ASSERT (OpenForWriting);\r
491 if (CreateDirectoryIfCreating) {\r
ac0a286f
MK
492 Status = CreateDirectory (\r
493 VirtioFs,\r
494 DirNodeId,\r
495 LastComponent,\r
496 &NewNodeId,\r
497 &NewFuseHandle\r
498 );\r
de0e1190 499 } else {\r
ac0a286f
MK
500 Status = CreateRegularFile (\r
501 VirtioFs,\r
502 DirNodeId,\r
503 LastComponent,\r
504 &NewNodeId,\r
505 &NewFuseHandle\r
506 );\r
de0e1190 507 }\r
ac0a286f 508\r
de0e1190
LE
509 NewNodeIsDirectory = CreateDirectoryIfCreating;\r
510 }\r
511\r
512 //\r
513 // Regardless of the branch taken, we're done with DirNodeId.\r
514 //\r
515 if (DirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {\r
516 VirtioFsFuseForget (VirtioFs, DirNodeId);\r
517 }\r
518\r
519 if (EFI_ERROR (Status)) {\r
520 goto FreeNewCanonicalPath;\r
521 }\r
522\r
523 //\r
524 // Populate the new VIRTIO_FS_FILE object.\r
525 //\r
526 NewVirtioFsFile->Signature = VIRTIO_FS_FILE_SIG;\r
527 NewVirtioFsFile->SimpleFile.Revision = EFI_FILE_PROTOCOL_REVISION;\r
528 NewVirtioFsFile->SimpleFile.Open = VirtioFsSimpleFileOpen;\r
529 NewVirtioFsFile->SimpleFile.Close = VirtioFsSimpleFileClose;\r
530 NewVirtioFsFile->SimpleFile.Delete = VirtioFsSimpleFileDelete;\r
531 NewVirtioFsFile->SimpleFile.Read = VirtioFsSimpleFileRead;\r
532 NewVirtioFsFile->SimpleFile.Write = VirtioFsSimpleFileWrite;\r
533 NewVirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;\r
534 NewVirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;\r
535 NewVirtioFsFile->SimpleFile.GetInfo = VirtioFsSimpleFileGetInfo;\r
536 NewVirtioFsFile->SimpleFile.SetInfo = VirtioFsSimpleFileSetInfo;\r
537 NewVirtioFsFile->SimpleFile.Flush = VirtioFsSimpleFileFlush;\r
538 NewVirtioFsFile->IsDirectory = NewNodeIsDirectory;\r
539 NewVirtioFsFile->IsOpenForWriting = OpenForWriting;\r
540 NewVirtioFsFile->OwnerFs = VirtioFs;\r
541 NewVirtioFsFile->CanonicalPathname = NewCanonicalPath;\r
c4edb49b 542 NewVirtioFsFile->FilePosition = 0;\r
de0e1190
LE
543 NewVirtioFsFile->NodeId = NewNodeId;\r
544 NewVirtioFsFile->FuseHandle = NewFuseHandle;\r
b845de89
LE
545 NewVirtioFsFile->FileInfoArray = NULL;\r
546 NewVirtioFsFile->SingleFileInfoSize = 0;\r
547 NewVirtioFsFile->NumFileInfo = 0;\r
548 NewVirtioFsFile->NextFileInfo = 0;\r
de0e1190
LE
549\r
550 //\r
551 // One more file is now open for the filesystem.\r
552 //\r
553 InsertTailList (&VirtioFs->OpenFiles, &NewVirtioFsFile->OpenFilesEntry);\r
554\r
555 *NewHandle = &NewVirtioFsFile->SimpleFile;\r
556 return EFI_SUCCESS;\r
557\r
558FreeNewCanonicalPath:\r
559 FreePool (NewCanonicalPath);\r
560\r
561FreeNewVirtioFsFile:\r
562 FreePool (NewVirtioFsFile);\r
563\r
564 return Status;\r
334c13e1 565}\r