summaryrefslogtreecommitdiffstats
path: root/FatPkg/EnhancedFatDxe/Flush.c
diff options
context:
space:
mode:
authorQing Huang <qing.huang@intel.com>2007-12-20 09:16:45 +0000
committerJordan Justen <jordan.l.justen@intel.com>2016-04-06 23:22:43 -0700
commitb9ec93308b33bcb0bb37d6213a76c3fed0b5bc0b (patch)
treeed4cc299df8f82781a6e6fae2022d2411ddc9c89 /FatPkg/EnhancedFatDxe/Flush.c
parentf0dc69e61bf2316dcf7cc75eb7e4ba374a5b2832 (diff)
downloadedk2-b9ec93308b33bcb0bb37d6213a76c3fed0b5bc0b.tar.gz
edk2-b9ec93308b33bcb0bb37d6213a76c3fed0b5bc0b.tar.bz2
edk2-b9ec93308b33bcb0bb37d6213a76c3fed0b5bc0b.zip
Add EDK II Prime FatPkg New Feature: Support both Unicode Collation and Unicode Collation 2 Protocols Support both Component Name and Component Name 2 Protocol.
(based on FatPkg commit e51cd032db84a6fb1f44a0605f80d96f5fdf4bc6) [jordan.l.justen@intel.com: Use script to relicense to 2-clause BSD] Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Acked-by: Mark Doran <mark.doran@intel.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'FatPkg/EnhancedFatDxe/Flush.c')
-rw-r--r--FatPkg/EnhancedFatDxe/Flush.c480
1 files changed, 480 insertions, 0 deletions
diff --git a/FatPkg/EnhancedFatDxe/Flush.c b/FatPkg/EnhancedFatDxe/Flush.c
new file mode 100644
index 0000000000..e058fa4cf8
--- /dev/null
+++ b/FatPkg/EnhancedFatDxe/Flush.c
@@ -0,0 +1,480 @@
+/*++
+
+Copyright (c) 2005 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+Module Name:
+
+ flush.c
+
+Abstract:
+
+ Routines that check references and flush OFiles
+
+Revision History
+
+--*/
+
+#include "Fat.h"
+
+EFI_STATUS
+EFIAPI
+FatFlush (
+ IN EFI_FILE *FHand
+ )
+/*++
+
+Routine Description:
+
+ Flushes all data associated with the file handle.
+
+Arguments:
+
+ FHand - Handle to file to flush.
+
+Returns:
+
+ EFI_SUCCESS - Flushed the file successfully.
+ EFI_WRITE_PROTECTED - The volume is read only.
+ EFI_ACCESS_DENIED - The file is read only.
+ Others - Flushing of the file failed.
+
+--*/
+{
+ FAT_IFILE *IFile;
+ FAT_OFILE *OFile;
+ FAT_VOLUME *Volume;
+ EFI_STATUS Status;
+
+ IFile = IFILE_FROM_FHAND (FHand);
+ OFile = IFile->OFile;
+ Volume = OFile->Volume;
+
+ //
+ // If the file has a permanent error, return it
+ //
+ if (EFI_ERROR (OFile->Error)) {
+ return OFile->Error;
+ }
+
+ if (Volume->ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+ //
+ // If read only, return error
+ //
+ if (IFile->ReadOnly) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Flush the OFile
+ //
+ FatAcquireLock ();
+ Status = FatOFileFlush (OFile);
+ Status = FatCleanupVolume (OFile->Volume, OFile, Status);
+ FatReleaseLock ();
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FatClose (
+ IN EFI_FILE *FHand
+ )
+/*++
+
+Routine Description:
+
+ Flushes & Closes the file handle.
+
+Arguments:
+
+ FHand - Handle to the file to delete.
+
+Returns:
+
+ EFI_SUCCESS - Closed the file successfully.
+
+--*/
+{
+ FAT_IFILE *IFile;
+ FAT_OFILE *OFile;
+ FAT_VOLUME *Volume;
+
+ IFile = IFILE_FROM_FHAND (FHand);
+ OFile = IFile->OFile;
+ Volume = OFile->Volume;
+
+ //
+ // Lock the volume
+ //
+ FatAcquireLock ();
+
+ //
+ // Close the file instance handle
+ //
+ FatIFileClose (IFile);
+
+ //
+ // Done. Unlock the volume
+ //
+ FatCleanupVolume (Volume, OFile, EFI_SUCCESS);
+ FatReleaseLock ();
+
+ //
+ // Close always succeed
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FatIFileClose (
+ FAT_IFILE *IFile
+ )
+/*++
+
+Routine Description:
+
+ Close the open file instance.
+
+Arguments:
+
+ IFile - Open file instance.
+
+Returns:
+
+ EFI_SUCCESS - Closed the file successfully.
+
+--*/
+{
+ FAT_OFILE *OFile;
+ FAT_VOLUME *Volume;
+
+ OFile = IFile->OFile;
+ Volume = OFile->Volume;
+
+ ASSERT_VOLUME_LOCKED (Volume);
+
+ //
+ // Remove the IFile struct
+ //
+ RemoveEntryList (&IFile->Link);
+
+ //
+ // Add the OFile to the check reference list
+ //
+ if (OFile->CheckLink.ForwardLink == NULL) {
+ InsertHeadList (&Volume->CheckRef, &OFile->CheckLink);
+ }
+ //
+ // Done. Free the open instance structure
+ //
+ FreePool (IFile);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FatOFileFlush (
+ IN FAT_OFILE *OFile
+ )
+/*++
+
+Routine Description:
+
+ Flush the data associated with an open file.
+ In this implementation, only last Mod/Access time is updated.
+
+Arguments:
+
+ OFile - The open file.
+
+Returns:
+
+ EFI_SUCCESS - The OFile is flushed successfully.
+ Others - An error occurred when flushing this OFile.
+
+--*/
+{
+ EFI_STATUS Status;
+ FAT_OFILE *Parent;
+ FAT_DIRENT *DirEnt;
+ FAT_DATE_TIME FatNow;
+
+ //
+ // Flush each entry up the tree while dirty
+ //
+ do {
+ //
+ // If the file has a permanant error, then don't write any
+ // of its data to the device (may be from different media)
+ //
+ if (EFI_ERROR (OFile->Error)) {
+ return OFile->Error;
+ }
+
+ Parent = OFile->Parent;
+ DirEnt = OFile->DirEnt;
+ if (OFile->Dirty) {
+ //
+ // Update the last modification time
+ //
+ FatGetCurrentFatTime (&FatNow);
+ CopyMem (&DirEnt->Entry.FileLastAccess, &FatNow.Date, sizeof (FAT_DATE));
+ if (!OFile->PreserveLastModification) {
+ FatGetCurrentFatTime (&DirEnt->Entry.FileModificationTime);
+ }
+
+ OFile->PreserveLastModification = FALSE;
+ if (OFile->Archive) {
+ DirEnt->Entry.Attributes |= FAT_ATTRIBUTE_ARCHIVE;
+ OFile->Archive = FALSE;
+ }
+ //
+ // Write the directory entry
+ //
+ if (Parent != NULL && !DirEnt->Invalid) {
+ //
+ // Write the OFile's directory entry
+ //
+ Status = FatStoreDirEnt (Parent, DirEnt);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ OFile->Dirty = FALSE;
+ }
+ //
+ // Check the parent
+ //
+ OFile = Parent;
+ } while (OFile != NULL);
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+FatCheckOFileRef (
+ IN FAT_OFILE *OFile
+ )
+/*++
+
+Routine Description:
+
+ Check the references of the OFile.
+ If the OFile (that is checked) is no longer
+ referenced, then it is freed.
+
+Arguments:
+
+ OFile - The OFile to be checked.
+
+Returns:
+
+ TRUE - The OFile is not referenced and freed.
+ FALSE - The OFile is kept.
+
+--*/
+{
+ //
+ // If the OFile is on the check ref list, remove it
+ //
+ if (OFile->CheckLink.ForwardLink != NULL) {
+ RemoveEntryList (&OFile->CheckLink);
+ OFile->CheckLink.ForwardLink = NULL;
+ }
+
+ FatOFileFlush (OFile);
+ //
+ // Are there any references to this OFile?
+ //
+ if (!IsListEmpty (&OFile->Opens) || !IsListEmpty (&OFile->ChildHead)) {
+ //
+ // The OFile cannot be freed
+ //
+ return FALSE;
+ }
+ //
+ // Free the Ofile
+ //
+ FatCloseDirEnt (OFile->DirEnt);
+ return TRUE;
+}
+
+STATIC
+VOID
+FatCheckVolumeRef (
+ IN FAT_VOLUME *Volume
+ )
+/*++
+
+Routine Description:
+
+ Check the references of all open files on the volume.
+ Any open file (that is checked) that is no longer
+ referenced, is freed - and it's parent open file
+ is then referenced checked.
+
+Arguments:
+
+ Volume - The volume to check the pending open file list.
+
+Returns:
+
+ None
+
+--*/
+{
+ FAT_OFILE *OFile;
+ FAT_OFILE *Parent;
+
+ //
+ // Check all files on the pending check list
+ //
+ while (!IsListEmpty (&Volume->CheckRef)) {
+ //
+ // Start with the first file listed
+ //
+ Parent = OFILE_FROM_CHECKLINK (Volume->CheckRef.ForwardLink);
+ //
+ // Go up the tree cleaning up any un-referenced OFiles
+ //
+ while (Parent != NULL) {
+ OFile = Parent;
+ Parent = OFile->Parent;
+ if (!FatCheckOFileRef (OFile)) {
+ break;
+ }
+ }
+ }
+}
+
+EFI_STATUS
+FatCleanupVolume (
+ IN FAT_VOLUME *Volume,
+ IN FAT_OFILE *OFile,
+ IN EFI_STATUS EfiStatus
+ )
+/*++
+
+Routine Description:
+
+ Set error status for a specific OFile, reference checking the volume.
+ If volume is already marked as invalid, and all resources are freed
+ after reference checking, the file system protocol is uninstalled and
+ the volume structure is freed.
+
+Arguments:
+
+ Volume - the Volume that is to be reference checked and unlocked.
+ OFile - the OFile whose permanent error code is to be set.
+ EfiStatus - error code to be set.
+
+Returns:
+
+ EFI_SUCCESS - Clean up the volume successfully.
+ Others - Cleaning up of the volume is failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ //
+ // Flag the OFile
+ //
+ if (OFile != NULL) {
+ FatSetVolumeError (OFile, EfiStatus);
+ }
+ //
+ // Clean up any dangling OFiles that don't have IFiles
+ // we don't check return status here because we want the
+ // volume be cleaned up even the volume is invalid.
+ //
+ FatCheckVolumeRef (Volume);
+ if (Volume->Valid) {
+ //
+ // Update the free hint info. Volume->FreeInfoPos != 0
+ // indicates this a FAT32 volume
+ //
+ if (Volume->FreeInfoValid && Volume->FatDirty && Volume->FreeInfoPos) {
+ Status = FatDiskIo (Volume, WRITE_DISK, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // Update that the volume is not dirty
+ //
+ if (Volume->FatDirty && Volume->FatType != FAT12) {
+ Volume->FatDirty = FALSE;
+ Status = FatAccessVolumeDirty (Volume, WRITE_FAT, &Volume->NotDirtyValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // Flush all dirty cache entries to disk
+ //
+ Status = FatVolumeFlushCache (Volume);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // If the volume is cleared , remove it.
+ // The only time volume be invalidated is in DriverBindingStop.
+ //
+ if (Volume->Root == NULL && !Volume->Valid) {
+ //
+ // Free the volume structure
+ //
+ FatFreeVolume (Volume);
+ }
+
+ return EfiStatus;
+}
+
+VOID
+FatSetVolumeError (
+ IN FAT_OFILE *OFile,
+ IN EFI_STATUS Status
+ )
+/*++
+
+Routine Description:
+
+ Set the OFile and its child OFile with the error Status
+
+Arguments:
+
+ OFile - The OFile whose permanent error code is to be set.
+ Status - Error code to be set.
+
+Returns:
+
+ None
+
+--*/
+{
+ LIST_ENTRY *Link;
+ FAT_OFILE *ChildOFile;
+
+ //
+ // If this OFile doesn't already have an error, set one
+ //
+ if (!EFI_ERROR (OFile->Error)) {
+ OFile->Error = Status;
+ }
+ //
+ // Set the error on each child OFile
+ //
+ for (Link = OFile->ChildHead.ForwardLink; Link != &OFile->ChildHead; Link = Link->ForwardLink) {
+ ChildOFile = OFILE_FROM_CHILDLINK (Link);
+ FatSetVolumeError (ChildOFile, Status);
+ }
+}