3 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Routines that check references and flush OFiles
30 IN EFI_FILE_PROTOCOL
*FHand
,
31 IN EFI_FILE_IO_TOKEN
*Token
37 Flushes all data associated with the file handle.
41 FHand - Handle to file to flush.
42 Token - A pointer to the token associated with the transaction.
46 EFI_SUCCESS - Flushed the file successfully.
47 EFI_WRITE_PROTECTED - The volume is read only.
48 EFI_ACCESS_DENIED - The file is read only.
49 Others - Flushing of the file failed.
59 IFile
= IFILE_FROM_FHAND (FHand
);
61 Volume
= OFile
->Volume
;
65 // If the file has a permanent error, return it
67 if (EFI_ERROR (OFile
->Error
)) {
71 if (Volume
->ReadOnly
) {
72 return EFI_WRITE_PROTECTED
;
75 // If read only, return error
77 if (IFile
->ReadOnly
) {
78 return EFI_ACCESS_DENIED
;
82 FatWaitNonblockingTask (IFile
);
85 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
86 // But if it calls, the below check can avoid crash.
88 if (FHand
->Revision
< EFI_FILE_PROTOCOL_REVISION2
) {
89 return EFI_UNSUPPORTED
;
91 Task
= FatCreateTask (IFile
, Token
);
93 return EFI_OUT_OF_RESOURCES
;
101 Status
= FatOFileFlush (OFile
);
102 Status
= FatCleanupVolume (OFile
->Volume
, OFile
, Status
, Task
);
106 if (!EFI_ERROR (Status
)) {
107 Status
= FatQueueTask (IFile
, Task
);
109 FatDestroyTask (Task
);
119 IN EFI_FILE_PROTOCOL
*FHand
125 Flushes all data associated with the file handle.
129 FHand - Handle to file to flush.
133 EFI_SUCCESS - Flushed the file successfully.
134 EFI_WRITE_PROTECTED - The volume is read only.
135 EFI_ACCESS_DENIED - The file is read only.
136 Others - Flushing of the file failed.
140 return FatFlushEx (FHand
, NULL
);
146 IN EFI_FILE_PROTOCOL
*FHand
152 Flushes & Closes the file handle.
156 FHand - Handle to the file to delete.
160 EFI_SUCCESS - Closed the file successfully.
168 IFile
= IFILE_FROM_FHAND (FHand
);
169 OFile
= IFile
->OFile
;
170 Volume
= OFile
->Volume
;
178 // Close the file instance handle
180 FatIFileClose (IFile
);
183 // Done. Unlock the volume
185 FatCleanupVolume (Volume
, OFile
, EFI_SUCCESS
, NULL
);
189 // Close always succeed
202 Close the open file instance.
206 IFile - Open file instance.
210 EFI_SUCCESS - Closed the file successfully.
217 OFile
= IFile
->OFile
;
218 Volume
= OFile
->Volume
;
220 ASSERT_VOLUME_LOCKED (Volume
);
222 FatWaitNonblockingTask (IFile
);
225 // Remove the IFile struct
227 RemoveEntryList (&IFile
->Link
);
230 // Add the OFile to the check reference list
232 if (OFile
->CheckLink
.ForwardLink
== NULL
) {
233 InsertHeadList (&Volume
->CheckRef
, &OFile
->CheckLink
);
236 // Done. Free the open instance structure
250 Flush the data associated with an open file.
251 In this implementation, only last Mod/Access time is updated.
255 OFile - The open file.
259 EFI_SUCCESS - The OFile is flushed successfully.
260 Others - An error occurred when flushing this OFile.
267 FAT_DATE_TIME FatNow
;
270 // Flush each entry up the tree while dirty
274 // If the file has a permanant error, then don't write any
275 // of its data to the device (may be from different media)
277 if (EFI_ERROR (OFile
->Error
)) {
281 Parent
= OFile
->Parent
;
282 DirEnt
= OFile
->DirEnt
;
285 // Update the last modification time
287 FatGetCurrentFatTime (&FatNow
);
288 CopyMem (&DirEnt
->Entry
.FileLastAccess
, &FatNow
.Date
, sizeof (FAT_DATE
));
289 if (!OFile
->PreserveLastModification
) {
290 FatGetCurrentFatTime (&DirEnt
->Entry
.FileModificationTime
);
293 OFile
->PreserveLastModification
= FALSE
;
294 if (OFile
->Archive
) {
295 DirEnt
->Entry
.Attributes
|= FAT_ATTRIBUTE_ARCHIVE
;
296 OFile
->Archive
= FALSE
;
299 // Write the directory entry
301 if (Parent
!= NULL
&& !DirEnt
->Invalid
) {
303 // Write the OFile's directory entry
305 Status
= FatStoreDirEnt (Parent
, DirEnt
);
306 if (EFI_ERROR (Status
)) {
311 OFile
->Dirty
= FALSE
;
317 } while (OFile
!= NULL
);
329 Check the references of the OFile.
330 If the OFile (that is checked) is no longer
331 referenced, then it is freed.
335 OFile - The OFile to be checked.
339 TRUE - The OFile is not referenced and freed.
340 FALSE - The OFile is kept.
345 // If the OFile is on the check ref list, remove it
347 if (OFile
->CheckLink
.ForwardLink
!= NULL
) {
348 RemoveEntryList (&OFile
->CheckLink
);
349 OFile
->CheckLink
.ForwardLink
= NULL
;
352 FatOFileFlush (OFile
);
354 // Are there any references to this OFile?
356 if (!IsListEmpty (&OFile
->Opens
) || !IsListEmpty (&OFile
->ChildHead
)) {
358 // The OFile cannot be freed
365 FatCloseDirEnt (OFile
->DirEnt
);
372 IN FAT_VOLUME
*Volume
378 Check the references of all open files on the volume.
379 Any open file (that is checked) that is no longer
380 referenced, is freed - and it's parent open file
381 is then referenced checked.
385 Volume - The volume to check the pending open file list.
397 // Check all files on the pending check list
399 while (!IsListEmpty (&Volume
->CheckRef
)) {
401 // Start with the first file listed
403 Parent
= OFILE_FROM_CHECKLINK (Volume
->CheckRef
.ForwardLink
);
405 // Go up the tree cleaning up any un-referenced OFiles
407 while (Parent
!= NULL
) {
409 Parent
= OFile
->Parent
;
410 if (!FatCheckOFileRef (OFile
)) {
419 IN FAT_VOLUME
*Volume
,
421 IN EFI_STATUS EfiStatus
,
428 Set error status for a specific OFile, reference checking the volume.
429 If volume is already marked as invalid, and all resources are freed
430 after reference checking, the file system protocol is uninstalled and
431 the volume structure is freed.
435 Volume - the Volume that is to be reference checked and unlocked.
436 OFile - the OFile whose permanent error code is to be set.
437 EfiStatus - error code to be set.
441 EFI_SUCCESS - Clean up the volume successfully.
442 Others - Cleaning up of the volume is failed.
451 FatSetVolumeError (OFile
, EfiStatus
);
454 // Clean up any dangling OFiles that don't have IFiles
455 // we don't check return status here because we want the
456 // volume be cleaned up even the volume is invalid.
458 FatCheckVolumeRef (Volume
);
461 // Update the free hint info. Volume->FreeInfoPos != 0
462 // indicates this a FAT32 volume
464 if (Volume
->FreeInfoValid
&& Volume
->FatDirty
&& Volume
->FreeInfoPos
) {
465 Status
= FatDiskIo (Volume
, WRITE_DISK
, Volume
->FreeInfoPos
, sizeof (FAT_INFO_SECTOR
), &Volume
->FatInfoSector
, Task
);
466 if (EFI_ERROR (Status
)) {
471 // Update that the volume is not dirty
473 if (Volume
->FatDirty
&& Volume
->FatType
!= FAT12
) {
474 Volume
->FatDirty
= FALSE
;
475 Status
= FatAccessVolumeDirty (Volume
, WRITE_FAT
, &Volume
->NotDirtyValue
);
476 if (EFI_ERROR (Status
)) {
481 // Flush all dirty cache entries to disk
483 Status
= FatVolumeFlushCache (Volume
, Task
);
484 if (EFI_ERROR (Status
)) {
489 // If the volume is cleared , remove it.
490 // The only time volume be invalidated is in DriverBindingStop.
492 if (Volume
->Root
== NULL
&& !Volume
->Valid
) {
494 // Free the volume structure
496 FatFreeVolume (Volume
);
511 Set the OFile and its child OFile with the error Status
515 OFile - The OFile whose permanent error code is to be set.
516 Status - Error code to be set.
525 FAT_OFILE
*ChildOFile
;
528 // If this OFile doesn't already have an error, set one
530 if (!EFI_ERROR (OFile
->Error
)) {
531 OFile
->Error
= Status
;
534 // Set the error on each child OFile
536 for (Link
= OFile
->ChildHead
.ForwardLink
; Link
!= &OFile
->ChildHead
; Link
= Link
->ForwardLink
) {
537 ChildOFile
= OFILE_FROM_CHILDLINK (Link
);
538 FatSetVolumeError (ChildOFile
, Status
);