]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/EnhancedFatDxe/Flush.c
FatPkg/EnhancedFatDxe: Make function prototype align with definition
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / Flush.c
CommitLineData
b9ec9330
QH
1/*++\r
2\r
149d6335 3Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
6163cc98 4This program and the accompanying materials are licensed and made available\r
b9ec9330
QH
5under the terms and conditions of the BSD License which accompanies this\r
6distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12\r
13Module Name:\r
14\r
15 flush.c\r
16\r
17Abstract:\r
18\r
19 Routines that check references and flush OFiles\r
20\r
21Revision History\r
22\r
23--*/\r
24\r
25#include "Fat.h"\r
26\r
27EFI_STATUS\r
28EFIAPI\r
149d6335
RN
29FatFlushEx (\r
30 IN EFI_FILE_PROTOCOL *FHand,\r
31 IN EFI_FILE_IO_TOKEN *Token\r
b9ec9330
QH
32 )\r
33/*++\r
34\r
35Routine Description:\r
36\r
37 Flushes all data associated with the file handle.\r
38\r
39Arguments:\r
40\r
41 FHand - Handle to file to flush.\r
149d6335 42 Token - A pointer to the token associated with the transaction.\r
b9ec9330
QH
43\r
44Returns:\r
45\r
46 EFI_SUCCESS - Flushed the file successfully.\r
47 EFI_WRITE_PROTECTED - The volume is read only.\r
48 EFI_ACCESS_DENIED - The file is read only.\r
49 Others - Flushing of the file failed.\r
50\r
51--*/\r
52{\r
53 FAT_IFILE *IFile;\r
54 FAT_OFILE *OFile;\r
55 FAT_VOLUME *Volume;\r
56 EFI_STATUS Status;\r
149d6335 57 FAT_TASK *Task;\r
b9ec9330
QH
58\r
59 IFile = IFILE_FROM_FHAND (FHand);\r
60 OFile = IFile->OFile;\r
61 Volume = OFile->Volume;\r
149d6335 62 Task = NULL;\r
b9ec9330
QH
63\r
64 //\r
65 // If the file has a permanent error, return it\r
66 //\r
67 if (EFI_ERROR (OFile->Error)) {\r
68 return OFile->Error;\r
69 }\r
70\r
71 if (Volume->ReadOnly) {\r
72 return EFI_WRITE_PROTECTED;\r
73 }\r
74 //\r
75 // If read only, return error\r
76 //\r
77 if (IFile->ReadOnly) {\r
78 return EFI_ACCESS_DENIED;\r
79 }\r
149d6335
RN
80\r
81 if (Token == NULL) {\r
82 FatWaitNonblockingTask (IFile);\r
83 } else {\r
84 //\r
85 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.\r
86 // But if it calls, the below check can avoid crash.\r
87 //\r
88 if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {\r
89 return EFI_UNSUPPORTED;\r
90 }\r
91 Task = FatCreateTask (IFile, Token);\r
92 if (Task == NULL) {\r
93 return EFI_OUT_OF_RESOURCES;\r
94 }\r
95 }\r
96\r
b9ec9330
QH
97 //\r
98 // Flush the OFile\r
99 //\r
100 FatAcquireLock ();\r
101 Status = FatOFileFlush (OFile);\r
149d6335 102 Status = FatCleanupVolume (OFile->Volume, OFile, Status, Task);\r
b9ec9330 103 FatReleaseLock ();\r
149d6335
RN
104\r
105 if (Token != NULL) {\r
106 if (!EFI_ERROR (Status)) {\r
107 Status = FatQueueTask (IFile, Task);\r
108 } else {\r
109 FatDestroyTask (Task);\r
110 }\r
111 }\r
112\r
b9ec9330
QH
113 return Status;\r
114}\r
115\r
149d6335
RN
116EFI_STATUS\r
117EFIAPI\r
118FatFlush (\r
119 IN EFI_FILE_PROTOCOL *FHand\r
120 )\r
121/*++\r
122\r
123Routine Description:\r
124\r
125 Flushes all data associated with the file handle.\r
126\r
127Arguments:\r
128\r
129 FHand - Handle to file to flush.\r
130\r
131Returns:\r
132\r
133 EFI_SUCCESS - Flushed the file successfully.\r
134 EFI_WRITE_PROTECTED - The volume is read only.\r
135 EFI_ACCESS_DENIED - The file is read only.\r
136 Others - Flushing of the file failed.\r
137\r
138--*/\r
139{\r
140 return FatFlushEx (FHand, NULL);\r
141}\r
142\r
b9ec9330
QH
143EFI_STATUS\r
144EFIAPI\r
145FatClose (\r
dba03ba1 146 IN EFI_FILE_PROTOCOL *FHand\r
b9ec9330
QH
147 )\r
148/*++\r
149\r
150Routine Description:\r
151\r
152 Flushes & Closes the file handle.\r
153\r
154Arguments:\r
155\r
156 FHand - Handle to the file to delete.\r
157\r
158Returns:\r
159\r
160 EFI_SUCCESS - Closed the file successfully.\r
161\r
162--*/\r
163{\r
164 FAT_IFILE *IFile;\r
165 FAT_OFILE *OFile;\r
166 FAT_VOLUME *Volume;\r
167\r
168 IFile = IFILE_FROM_FHAND (FHand);\r
169 OFile = IFile->OFile;\r
170 Volume = OFile->Volume;\r
171\r
172 //\r
173 // Lock the volume\r
174 //\r
175 FatAcquireLock ();\r
176\r
177 //\r
178 // Close the file instance handle\r
179 //\r
180 FatIFileClose (IFile);\r
181\r
182 //\r
183 // Done. Unlock the volume\r
184 //\r
149d6335 185 FatCleanupVolume (Volume, OFile, EFI_SUCCESS, NULL);\r
b9ec9330
QH
186 FatReleaseLock ();\r
187\r
188 //\r
189 // Close always succeed\r
190 //\r
191 return EFI_SUCCESS;\r
192}\r
193\r
194EFI_STATUS\r
195FatIFileClose (\r
196 FAT_IFILE *IFile\r
197 )\r
198/*++\r
199\r
200Routine Description:\r
201\r
202 Close the open file instance.\r
203\r
204Arguments:\r
205\r
206 IFile - Open file instance.\r
207\r
208Returns:\r
209\r
210 EFI_SUCCESS - Closed the file successfully.\r
211\r
212--*/\r
213{\r
214 FAT_OFILE *OFile;\r
215 FAT_VOLUME *Volume;\r
216\r
217 OFile = IFile->OFile;\r
218 Volume = OFile->Volume;\r
219\r
220 ASSERT_VOLUME_LOCKED (Volume);\r
221\r
149d6335
RN
222 FatWaitNonblockingTask (IFile);\r
223\r
b9ec9330
QH
224 //\r
225 // Remove the IFile struct\r
226 //\r
227 RemoveEntryList (&IFile->Link);\r
228\r
229 //\r
230 // Add the OFile to the check reference list\r
231 //\r
232 if (OFile->CheckLink.ForwardLink == NULL) {\r
233 InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);\r
234 }\r
235 //\r
236 // Done. Free the open instance structure\r
237 //\r
238 FreePool (IFile);\r
239 return EFI_SUCCESS;\r
240}\r
241\r
242EFI_STATUS\r
243FatOFileFlush (\r
244 IN FAT_OFILE *OFile\r
245 )\r
246/*++\r
247\r
248Routine Description:\r
249\r
250 Flush the data associated with an open file.\r
251 In this implementation, only last Mod/Access time is updated.\r
252\r
253Arguments:\r
254\r
255 OFile - The open file.\r
256\r
257Returns:\r
258\r
259 EFI_SUCCESS - The OFile is flushed successfully.\r
260 Others - An error occurred when flushing this OFile.\r
261\r
262--*/\r
263{\r
264 EFI_STATUS Status;\r
265 FAT_OFILE *Parent;\r
266 FAT_DIRENT *DirEnt;\r
267 FAT_DATE_TIME FatNow;\r
268\r
269 //\r
270 // Flush each entry up the tree while dirty\r
271 //\r
272 do {\r
273 //\r
274 // If the file has a permanant error, then don't write any\r
275 // of its data to the device (may be from different media)\r
276 //\r
277 if (EFI_ERROR (OFile->Error)) {\r
278 return OFile->Error;\r
279 }\r
280\r
281 Parent = OFile->Parent;\r
282 DirEnt = OFile->DirEnt;\r
283 if (OFile->Dirty) {\r
284 //\r
285 // Update the last modification time\r
286 //\r
287 FatGetCurrentFatTime (&FatNow);\r
288 CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));\r
289 if (!OFile->PreserveLastModification) {\r
290 FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);\r
291 }\r
292\r
293 OFile->PreserveLastModification = FALSE;\r
294 if (OFile->Archive) {\r
295 DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;\r
296 OFile->Archive = FALSE;\r
297 }\r
298 //\r
299 // Write the directory entry\r
300 //\r
301 if (Parent != NULL && !DirEnt->Invalid) {\r
302 //\r
303 // Write the OFile's directory entry\r
304 //\r
305 Status = FatStoreDirEnt (Parent, DirEnt);\r
306 if (EFI_ERROR (Status)) {\r
307 return Status;\r
308 }\r
309 }\r
310\r
311 OFile->Dirty = FALSE;\r
312 }\r
313 //\r
314 // Check the parent\r
315 //\r
316 OFile = Parent;\r
317 } while (OFile != NULL);\r
318 return EFI_SUCCESS;\r
319}\r
320\r
321BOOLEAN\r
322FatCheckOFileRef (\r
323 IN FAT_OFILE *OFile\r
324 )\r
325/*++\r
326\r
327Routine Description:\r
328\r
329 Check the references of the OFile.\r
330 If the OFile (that is checked) is no longer\r
331 referenced, then it is freed.\r
332\r
333Arguments:\r
334\r
335 OFile - The OFile to be checked.\r
336\r
337Returns:\r
338\r
339 TRUE - The OFile is not referenced and freed.\r
340 FALSE - The OFile is kept.\r
341\r
342--*/\r
343{\r
344 //\r
345 // If the OFile is on the check ref list, remove it\r
346 //\r
347 if (OFile->CheckLink.ForwardLink != NULL) {\r
348 RemoveEntryList (&OFile->CheckLink);\r
349 OFile->CheckLink.ForwardLink = NULL;\r
350 }\r
351\r
352 FatOFileFlush (OFile);\r
353 //\r
354 // Are there any references to this OFile?\r
355 //\r
356 if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {\r
357 //\r
358 // The OFile cannot be freed\r
359 //\r
360 return FALSE;\r
361 }\r
362 //\r
363 // Free the Ofile\r
364 //\r
365 FatCloseDirEnt (OFile->DirEnt);\r
366 return TRUE;\r
367}\r
368\r
369STATIC\r
370VOID\r
371FatCheckVolumeRef (\r
372 IN FAT_VOLUME *Volume\r
373 )\r
374/*++\r
375\r
376Routine Description:\r
377\r
378 Check the references of all open files on the volume.\r
379 Any open file (that is checked) that is no longer\r
380 referenced, is freed - and it's parent open file\r
381 is then referenced checked.\r
382\r
383Arguments:\r
384\r
385 Volume - The volume to check the pending open file list.\r
386\r
387Returns:\r
388\r
389 None\r
390\r
391--*/\r
392{\r
393 FAT_OFILE *OFile;\r
394 FAT_OFILE *Parent;\r
395\r
396 //\r
397 // Check all files on the pending check list\r
398 //\r
399 while (!IsListEmpty (&Volume->CheckRef)) {\r
400 //\r
401 // Start with the first file listed\r
402 //\r
403 Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);\r
404 //\r
405 // Go up the tree cleaning up any un-referenced OFiles\r
406 //\r
407 while (Parent != NULL) {\r
408 OFile = Parent;\r
409 Parent = OFile->Parent;\r
410 if (!FatCheckOFileRef (OFile)) {\r
411 break;\r
412 }\r
413 }\r
414 }\r
415}\r
416\r
417EFI_STATUS\r
418FatCleanupVolume (\r
419 IN FAT_VOLUME *Volume,\r
420 IN FAT_OFILE *OFile,\r
149d6335
RN
421 IN EFI_STATUS EfiStatus,\r
422 IN FAT_TASK *Task\r
b9ec9330
QH
423 )\r
424/*++\r
425\r
426Routine Description:\r
427\r
428 Set error status for a specific OFile, reference checking the volume.\r
429 If volume is already marked as invalid, and all resources are freed\r
430 after reference checking, the file system protocol is uninstalled and\r
431 the volume structure is freed.\r
432\r
433Arguments:\r
434\r
435 Volume - the Volume that is to be reference checked and unlocked.\r
436 OFile - the OFile whose permanent error code is to be set.\r
437 EfiStatus - error code to be set.\r
438\r
439Returns:\r
440\r
441 EFI_SUCCESS - Clean up the volume successfully.\r
442 Others - Cleaning up of the volume is failed.\r
443\r
444--*/\r
445{\r
446 EFI_STATUS Status;\r
447 //\r
448 // Flag the OFile\r
449 //\r
450 if (OFile != NULL) {\r
451 FatSetVolumeError (OFile, EfiStatus);\r
452 }\r
453 //\r
454 // Clean up any dangling OFiles that don't have IFiles\r
455 // we don't check return status here because we want the\r
456 // volume be cleaned up even the volume is invalid.\r
457 //\r
458 FatCheckVolumeRef (Volume);\r
459 if (Volume->Valid) {\r
460 //\r
461 // Update the free hint info. Volume->FreeInfoPos != 0\r
462 // indicates this a FAT32 volume\r
463 //\r
464 if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {\r
149d6335 465 Status = FatDiskIo (Volume, WRITE_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, Task);\r
b9ec9330
QH
466 if (EFI_ERROR (Status)) {\r
467 return Status;\r
468 }\r
469 }\r
470 //\r
471 // Update that the volume is not dirty\r
472 //\r
473 if (Volume->FatDirty && Volume->FatType != FAT12) {\r
474 Volume->FatDirty = FALSE;\r
475 Status = FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->NotDirtyValue);\r
476 if (EFI_ERROR (Status)) {\r
477 return Status;\r
478 }\r
479 }\r
480 //\r
481 // Flush all dirty cache entries to disk\r
482 //\r
149d6335 483 Status = FatVolumeFlushCache (Volume, Task);\r
b9ec9330
QH
484 if (EFI_ERROR (Status)) {\r
485 return Status;\r
486 }\r
487 }\r
488 //\r
489 // If the volume is cleared , remove it.\r
490 // The only time volume be invalidated is in DriverBindingStop.\r
491 //\r
492 if (Volume->Root == NULL && !Volume->Valid) {\r
493 //\r
494 // Free the volume structure\r
495 //\r
496 FatFreeVolume (Volume);\r
497 }\r
498\r
499 return EfiStatus;\r
500}\r
501\r
502VOID\r
503FatSetVolumeError (\r
504 IN FAT_OFILE *OFile,\r
505 IN EFI_STATUS Status\r
506 )\r
507/*++\r
508\r
509Routine Description:\r
510\r
511 Set the OFile and its child OFile with the error Status\r
512\r
513Arguments:\r
514\r
515 OFile - The OFile whose permanent error code is to be set.\r
516 Status - Error code to be set.\r
517\r
518Returns:\r
519\r
520 None\r
521\r
522--*/\r
523{\r
524 LIST_ENTRY *Link;\r
525 FAT_OFILE *ChildOFile;\r
526\r
527 //\r
528 // If this OFile doesn't already have an error, set one\r
529 //\r
530 if (!EFI_ERROR (OFile->Error)) {\r
531 OFile->Error = Status;\r
532 }\r
533 //\r
534 // Set the error on each child OFile\r
535 //\r
536 for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {\r
537 ChildOFile = OFILE_FROM_CHILDLINK (Link);\r
538 FatSetVolumeError (ChildOFile, Status);\r
539 }\r
540}\r