TianoCore EDK2 master
Loading...
Searching...
No Matches
Flush.c
Go to the documentation of this file.
1
10#include "Fat.h"
11
26EFIAPI
28 IN EFI_FILE_PROTOCOL *FHand,
30 )
31{
32 FAT_IFILE *IFile;
33 FAT_OFILE *OFile;
34 FAT_VOLUME *Volume;
35 EFI_STATUS Status;
36 FAT_TASK *Task;
37
38 IFile = IFILE_FROM_FHAND (FHand);
39 OFile = IFile->OFile;
40 Volume = OFile->Volume;
41 Task = NULL;
42
43 //
44 // If the file has a permanent error, return it
45 //
46 if (EFI_ERROR (OFile->Error)) {
47 return OFile->Error;
48 }
49
50 if (Volume->ReadOnly) {
51 return EFI_WRITE_PROTECTED;
52 }
53
54 //
55 // If read only, return error
56 //
57 if (IFile->ReadOnly) {
58 return EFI_ACCESS_DENIED;
59 }
60
61 if (Token == NULL) {
63 } else {
64 //
65 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
66 // But if it calls, the below check can avoid crash.
67 //
68 if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
69 return EFI_UNSUPPORTED;
70 }
71
72 Task = FatCreateTask (IFile, Token);
73 if (Task == NULL) {
74 return EFI_OUT_OF_RESOURCES;
75 }
76 }
77
78 //
79 // Flush the OFile
80 //
82 Status = FatOFileFlush (OFile);
83 Status = FatCleanupVolume (OFile->Volume, OFile, Status, Task);
85
86 if (Token != NULL) {
87 if (!EFI_ERROR (Status)) {
88 Status = FatQueueTask (IFile, Task);
89 } else {
90 FatDestroyTask (Task);
91 }
92 }
93
94 return Status;
95}
96
110EFIAPI
112 IN EFI_FILE_PROTOCOL *FHand
113 )
114{
115 return FatFlushEx (FHand, NULL);
116}
117
128EFIAPI
130 IN EFI_FILE_PROTOCOL *FHand
131 )
132{
133 FAT_IFILE *IFile;
134 FAT_OFILE *OFile;
135 FAT_VOLUME *Volume;
136
137 IFile = IFILE_FROM_FHAND (FHand);
138 OFile = IFile->OFile;
139 Volume = OFile->Volume;
140
141 //
142 // Lock the volume
143 //
145
146 //
147 // Close the file instance handle
148 //
149 FatIFileClose (IFile);
150
151 //
152 // Done. Unlock the volume
153 //
154 FatCleanupVolume (Volume, OFile, EFI_SUCCESS, NULL);
156
157 //
158 // Close always succeed
159 //
160 return EFI_SUCCESS;
161}
162
174 FAT_IFILE *IFile
175 )
176{
177 FAT_OFILE *OFile;
178 FAT_VOLUME *Volume;
179
180 OFile = IFile->OFile;
181 Volume = OFile->Volume;
182
183 ASSERT_VOLUME_LOCKED (Volume);
184
186
187 //
188 // Remove the IFile struct
189 //
190 RemoveEntryList (&IFile->Link);
191
192 //
193 // Add the OFile to the check reference list
194 //
195 if (OFile->CheckLink.ForwardLink == NULL) {
196 InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
197 }
198
199 //
200 // Done. Free the open instance structure
201 //
202 FreePool (IFile);
203 return EFI_SUCCESS;
204}
205
219 IN FAT_OFILE *OFile
220 )
221{
222 EFI_STATUS Status;
223 FAT_OFILE *Parent;
224 FAT_DIRENT *DirEnt;
225 FAT_DATE_TIME FatNow;
226
227 //
228 // Flush each entry up the tree while dirty
229 //
230 do {
231 //
232 // If the file has a permanent error, then don't write any
233 // of its data to the device (may be from different media)
234 //
235 if (EFI_ERROR (OFile->Error)) {
236 return OFile->Error;
237 }
238
239 Parent = OFile->Parent;
240 DirEnt = OFile->DirEnt;
241 if (OFile->Dirty) {
242 //
243 // Update the last modification time
244 //
245 FatGetCurrentFatTime (&FatNow);
246 CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));
247 if (!OFile->PreserveLastModification) {
248 FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);
249 }
250
251 OFile->PreserveLastModification = FALSE;
252 if (OFile->Archive) {
253 DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;
254 OFile->Archive = FALSE;
255 }
256
257 //
258 // Write the directory entry
259 //
260 if ((Parent != NULL) && !DirEnt->Invalid) {
261 //
262 // Write the OFile's directory entry
263 //
264 Status = FatStoreDirEnt (Parent, DirEnt);
265 if (EFI_ERROR (Status)) {
266 return Status;
267 }
268 }
269
270 OFile->Dirty = FALSE;
271 }
272
273 //
274 // Check the parent
275 //
276 OFile = Parent;
277 } while (OFile != NULL);
278
279 return EFI_SUCCESS;
280}
281
294BOOLEAN
296 IN FAT_OFILE *OFile
297 )
298{
299 //
300 // If the OFile is on the check ref list, remove it
301 //
302 if (OFile->CheckLink.ForwardLink != NULL) {
303 RemoveEntryList (&OFile->CheckLink);
304 OFile->CheckLink.ForwardLink = NULL;
305 }
306
307 FatOFileFlush (OFile);
308 //
309 // Are there any references to this OFile?
310 //
311 if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {
312 //
313 // The OFile cannot be freed
314 //
315 return FALSE;
316 }
317
318 //
319 // Free the Ofile
320 //
321 FatCloseDirEnt (OFile->DirEnt);
322 return TRUE;
323}
324
335STATIC
336VOID
338 IN FAT_VOLUME *Volume
339 )
340{
341 FAT_OFILE *OFile;
342 FAT_OFILE *Parent;
343
344 //
345 // Check all files on the pending check list
346 //
347 while (!IsListEmpty (&Volume->CheckRef)) {
348 //
349 // Start with the first file listed
350 //
351 Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);
352 //
353 // Go up the tree cleaning up any un-referenced OFiles
354 //
355 while (Parent != NULL) {
356 OFile = Parent;
357 Parent = OFile->Parent;
358 if (!FatCheckOFileRef (OFile)) {
359 break;
360 }
361 }
362 }
363}
364
383 IN FAT_VOLUME *Volume,
384 IN FAT_OFILE *OFile,
385 IN EFI_STATUS EfiStatus,
386 IN FAT_TASK *Task
387 )
388{
389 EFI_STATUS Status;
390
391 //
392 // Flag the OFile
393 //
394 if (OFile != NULL) {
395 FatSetVolumeError (OFile, EfiStatus);
396 }
397
398 //
399 // Clean up any dangling OFiles that don't have IFiles
400 // we don't check return status here because we want the
401 // volume be cleaned up even the volume is invalid.
402 //
403 FatCheckVolumeRef (Volume);
404 if (Volume->Valid) {
405 //
406 // Update the free hint info. Volume->FreeInfoPos != 0
407 // indicates this a FAT32 volume
408 //
409 if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {
410 Status = FatDiskIo (Volume, WriteDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, Task);
411 if (EFI_ERROR (Status)) {
412 return Status;
413 }
414 }
415
416 //
417 // Update that the volume is not dirty
418 //
419 if (Volume->FatDirty && (Volume->FatType != Fat12)) {
420 Volume->FatDirty = FALSE;
421 Status = FatAccessVolumeDirty (Volume, WriteFat, &Volume->NotDirtyValue);
422 if (EFI_ERROR (Status)) {
423 return Status;
424 }
425 }
426
427 //
428 // Flush all dirty cache entries to disk
429 //
430 Status = FatVolumeFlushCache (Volume, Task);
431 if (EFI_ERROR (Status)) {
432 return Status;
433 }
434 }
435
436 //
437 // If the volume is cleared , remove it.
438 // The only time volume be invalidated is in DriverBindingStop.
439 //
440 if ((Volume->Root == NULL) && !Volume->Valid) {
441 //
442 // Free the volume structure
443 //
444 FatFreeVolume (Volume);
445 }
446
447 return EfiStatus;
448}
449
458VOID
460 IN FAT_OFILE *OFile,
461 IN EFI_STATUS Status
462 )
463{
464 LIST_ENTRY *Link;
465 FAT_OFILE *ChildOFile;
466
467 //
468 // If this OFile doesn't already have an error, set one
469 //
470 if (!EFI_ERROR (OFile->Error)) {
471 OFile->Error = Status;
472 }
473
474 //
475 // Set the error on each child OFile
476 //
477 for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {
478 ChildOFile = OFILE_FROM_CHILDLINK (Link);
479 FatSetVolumeError (ChildOFile, Status);
480 }
481}
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS FatStoreDirEnt(IN FAT_OFILE *OFile, IN FAT_DIRENT *DirEnt)
VOID FatCloseDirEnt(IN FAT_DIRENT *DirEnt)
EFI_STATUS FatVolumeFlushCache(IN FAT_VOLUME *Volume, IN FAT_TASK *Task)
Definition: DiskCache.c:595
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID FatFreeVolume(IN FAT_VOLUME *Volume)
Definition: Misc.c:460
VOID FatDestroyTask(FAT_TASK *Task)
Definition: Misc.c:51
FAT_TASK * FatCreateTask(FAT_IFILE *IFile, EFI_FILE_IO_TOKEN *Token)
Definition: Misc.c:24
EFI_STATUS FatQueueTask(IN FAT_IFILE *IFile, IN FAT_TASK *Task)
Definition: Misc.c:124
VOID FatWaitNonblockingTask(FAT_IFILE *IFile)
Definition: Misc.c:75
EFI_STATUS FatDiskIo(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN UINT64 Offset, IN UINTN BufferSize, IN OUT VOID *Buffer, IN FAT_TASK *Task)
Definition: Misc.c:315
EFI_STATUS FatAccessVolumeDirty(IN FAT_VOLUME *Volume, IN IO_MODE IoMode, IN VOID *DirtyValue)
Definition: Misc.c:230
VOID FatAcquireLock(VOID)
Definition: Misc.c:395
VOID FatReleaseLock(VOID)
Definition: Misc.c:426
VOID FatGetCurrentFatTime(OUT FAT_DATE_TIME *FatTime)
Definition: Misc.c:543
EFI_STATUS FatOFileFlush(IN FAT_OFILE *OFile)
Definition: Flush.c:218
EFI_STATUS EFIAPI FatFlushEx(IN EFI_FILE_PROTOCOL *FHand, IN EFI_FILE_IO_TOKEN *Token)
Definition: Flush.c:27
EFI_STATUS FatIFileClose(FAT_IFILE *IFile)
Definition: Flush.c:173
BOOLEAN FatCheckOFileRef(IN FAT_OFILE *OFile)
Definition: Flush.c:295
EFI_STATUS EFIAPI FatFlush(IN EFI_FILE_PROTOCOL *FHand)
Definition: Flush.c:111
VOID FatSetVolumeError(IN FAT_OFILE *OFile, IN EFI_STATUS Status)
Definition: Flush.c:459
EFI_STATUS EFIAPI FatClose(IN EFI_FILE_PROTOCOL *FHand)
Definition: Flush.c:129
STATIC VOID FatCheckVolumeRef(IN FAT_VOLUME *Volume)
Definition: Flush.c:337
EFI_STATUS FatCleanupVolume(IN FAT_VOLUME *Volume, IN FAT_OFILE *OFile, IN EFI_STATUS EfiStatus, IN FAT_TASK *Task)
Definition: Flush.c:382
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Fat.h:217
Definition: Fat.h:227