REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the FatPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			617 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			617 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Miscellaneous functions.
 | 
						|
 | 
						|
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Fat.h"
 | 
						|
UINT8  mMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Create the task
 | 
						|
 | 
						|
  @param  IFile                 - The instance of the open file.
 | 
						|
  @param  Token                 - A pointer to the token associated with the transaction.
 | 
						|
 | 
						|
  @return FAT_TASK *            - Return the task instance.
 | 
						|
 | 
						|
**/
 | 
						|
FAT_TASK *
 | 
						|
FatCreateTask (
 | 
						|
  FAT_IFILE          *IFile,
 | 
						|
  EFI_FILE_IO_TOKEN  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  FAT_TASK  *Task;
 | 
						|
 | 
						|
  Task = AllocateZeroPool (sizeof (*Task));
 | 
						|
  if (Task != NULL) {
 | 
						|
    Task->Signature   = FAT_TASK_SIGNATURE;
 | 
						|
    Task->IFile       = IFile;
 | 
						|
    Task->FileIoToken = Token;
 | 
						|
    InitializeListHead (&Task->Subtasks);
 | 
						|
    InitializeListHead (&Task->Link);
 | 
						|
  }
 | 
						|
 | 
						|
  return Task;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Destroy the task.
 | 
						|
 | 
						|
  @param  Task                  - The task to be destroyed.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatDestroyTask (
 | 
						|
  FAT_TASK  *Task
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY   *Link;
 | 
						|
  FAT_SUBTASK  *Subtask;
 | 
						|
 | 
						|
  Link = GetFirstNode (&Task->Subtasks);
 | 
						|
  while (!IsNull (&Task->Subtasks, Link)) {
 | 
						|
    Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
 | 
						|
    Link    = FatDestroySubtask (Subtask);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Task);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Wait all non-blocking requests complete.
 | 
						|
 | 
						|
  @param  IFile                 - The instance of the open file.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatWaitNonblockingTask (
 | 
						|
  FAT_IFILE  *IFile
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN  TaskQueueEmpty;
 | 
						|
 | 
						|
  do {
 | 
						|
    EfiAcquireLock (&FatTaskLock);
 | 
						|
    TaskQueueEmpty = IsListEmpty (&IFile->Tasks);
 | 
						|
    EfiReleaseLock (&FatTaskLock);
 | 
						|
  } while (!TaskQueueEmpty);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Remove the subtask from subtask list.
 | 
						|
 | 
						|
  @param  Subtask               - The subtask to be removed.
 | 
						|
 | 
						|
  @return LIST_ENTRY *          - The next node in the list.
 | 
						|
 | 
						|
**/
 | 
						|
LIST_ENTRY *
 | 
						|
FatDestroySubtask (
 | 
						|
  FAT_SUBTASK  *Subtask
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY  *Link;
 | 
						|
 | 
						|
  gBS->CloseEvent (Subtask->DiskIo2Token.Event);
 | 
						|
 | 
						|
  Link = RemoveEntryList (&Subtask->Link);
 | 
						|
  FreePool (Subtask);
 | 
						|
 | 
						|
  return Link;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Execute the task.
 | 
						|
 | 
						|
  @param  IFile                 - The instance of the open file.
 | 
						|
  @param  Task                  - The task to be executed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The task was executed successfully.
 | 
						|
  @return other                 - An error occurred when executing the task.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatQueueTask (
 | 
						|
  IN FAT_IFILE  *IFile,
 | 
						|
  IN FAT_TASK   *Task
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  LIST_ENTRY   *Link;
 | 
						|
  LIST_ENTRY   *NextLink;
 | 
						|
  FAT_SUBTASK  *Subtask;
 | 
						|
 | 
						|
  //
 | 
						|
  // Sometimes the Task doesn't contain any subtasks, signal the event directly.
 | 
						|
  //
 | 
						|
  if (IsListEmpty (&Task->Subtasks)) {
 | 
						|
    Task->FileIoToken->Status = EFI_SUCCESS;
 | 
						|
    gBS->SignalEvent (Task->FileIoToken->Event);
 | 
						|
    FreePool (Task);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  EfiAcquireLock (&FatTaskLock);
 | 
						|
  InsertTailList (&IFile->Tasks, &Task->Link);
 | 
						|
  EfiReleaseLock (&FatTaskLock);
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  //
 | 
						|
  // Use NextLink to store the next link of the list, because Link might be remove from the
 | 
						|
  // doubly-linked list and get freed in the end of current loop.
 | 
						|
  //
 | 
						|
  // Also, list operation APIs like IsNull() and GetNextNode() are avoided during the loop, since
 | 
						|
  // they may check the validity of doubly-linked lists by traversing them. These APIs cannot
 | 
						|
  // handle list elements being removed during the traverse.
 | 
						|
  //
 | 
						|
  for ( Link = GetFirstNode (&Task->Subtasks), NextLink = GetNextNode (&Task->Subtasks, Link)
 | 
						|
        ; Link != &Task->Subtasks
 | 
						|
        ; Link = NextLink, NextLink = Link->ForwardLink
 | 
						|
        )
 | 
						|
  {
 | 
						|
    Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
 | 
						|
    if (Subtask->Write) {
 | 
						|
      Status = IFile->OFile->Volume->DiskIo2->WriteDiskEx (
 | 
						|
                                                IFile->OFile->Volume->DiskIo2,
 | 
						|
                                                IFile->OFile->Volume->MediaId,
 | 
						|
                                                Subtask->Offset,
 | 
						|
                                                &Subtask->DiskIo2Token,
 | 
						|
                                                Subtask->BufferSize,
 | 
						|
                                                Subtask->Buffer
 | 
						|
                                                );
 | 
						|
    } else {
 | 
						|
      Status = IFile->OFile->Volume->DiskIo2->ReadDiskEx (
 | 
						|
                                                IFile->OFile->Volume->DiskIo2,
 | 
						|
                                                IFile->OFile->Volume->MediaId,
 | 
						|
                                                Subtask->Offset,
 | 
						|
                                                &Subtask->DiskIo2Token,
 | 
						|
                                                Subtask->BufferSize,
 | 
						|
                                                Subtask->Buffer
 | 
						|
                                                );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    EfiAcquireLock (&FatTaskLock);
 | 
						|
    //
 | 
						|
    // Remove all the remaining subtasks when failure.
 | 
						|
    // We shouldn't remove all the tasks because the non-blocking requests have
 | 
						|
    // been submitted and cannot be canceled.
 | 
						|
    //
 | 
						|
    while (!IsNull (&Task->Subtasks, Link)) {
 | 
						|
      Subtask = CR (Link, FAT_SUBTASK, Link, FAT_SUBTASK_SIGNATURE);
 | 
						|
      Link    = FatDestroySubtask (Subtask);
 | 
						|
    }
 | 
						|
 | 
						|
    if (IsListEmpty (&Task->Subtasks)) {
 | 
						|
      RemoveEntryList (&Task->Link);
 | 
						|
      FreePool (Task);
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // If one or more subtasks have been already submitted, set FileIoToken
 | 
						|
      // to NULL so that the callback won't signal the event.
 | 
						|
      //
 | 
						|
      Task->FileIoToken = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    EfiReleaseLock (&FatTaskLock);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Set the volume as dirty or not.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  IoMode                - The access mode.
 | 
						|
  @param  DirtyValue            - Set the volume as dirty or not.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - Set the new FAT entry value successfully.
 | 
						|
  @return other                 - An error occurred when operation the FAT entries.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatAccessVolumeDirty (
 | 
						|
  IN FAT_VOLUME  *Volume,
 | 
						|
  IN IO_MODE     IoMode,
 | 
						|
  IN VOID        *DirtyValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  WriteCount;
 | 
						|
 | 
						|
  WriteCount = Volume->FatEntrySize;
 | 
						|
  return FatDiskIo (Volume, IoMode, Volume->FatPos + WriteCount, WriteCount, DirtyValue, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Invoke a notification event.
 | 
						|
 | 
						|
  @param  Event                 Event whose notification function is being invoked.
 | 
						|
  @param  Context               The pointer to the notification function's context,
 | 
						|
                                which is implementation-dependent.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
FatOnAccessComplete (
 | 
						|
  IN  EFI_EVENT  Event,
 | 
						|
  IN  VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  FAT_SUBTASK  *Subtask;
 | 
						|
  FAT_TASK     *Task;
 | 
						|
 | 
						|
  //
 | 
						|
  // Avoid someone in future breaks the below assumption.
 | 
						|
  //
 | 
						|
  ASSERT (EfiGetCurrentTpl () == FatTaskLock.Tpl);
 | 
						|
 | 
						|
  Subtask = (FAT_SUBTASK *)Context;
 | 
						|
  Task    = Subtask->Task;
 | 
						|
  Status  = Subtask->DiskIo2Token.TransactionStatus;
 | 
						|
 | 
						|
  ASSERT (Task->Signature    == FAT_TASK_SIGNATURE);
 | 
						|
  ASSERT (Subtask->Signature == FAT_SUBTASK_SIGNATURE);
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove the task unconditionally
 | 
						|
  //
 | 
						|
  FatDestroySubtask (Subtask);
 | 
						|
 | 
						|
  //
 | 
						|
  // Task->FileIoToken is NULL which means the task will be ignored (just recycle the subtask and task memory).
 | 
						|
  //
 | 
						|
  if (Task->FileIoToken != NULL) {
 | 
						|
    if (IsListEmpty (&Task->Subtasks) || EFI_ERROR (Status)) {
 | 
						|
      Task->FileIoToken->Status = Status;
 | 
						|
      gBS->SignalEvent (Task->FileIoToken->Event);
 | 
						|
      //
 | 
						|
      // Mark Task->FileIoToken to NULL so that the subtasks belonging to the task will be ignored.
 | 
						|
      //
 | 
						|
      Task->FileIoToken = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsListEmpty (&Task->Subtasks)) {
 | 
						|
    RemoveEntryList (&Task->Link);
 | 
						|
    FreePool (Task);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  General disk access function.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  IoMode                - The access mode (disk read/write or cache access).
 | 
						|
  @param  Offset                - The starting byte offset to read from.
 | 
						|
  @param  BufferSize            - Size of Buffer.
 | 
						|
  @param  Buffer                - Buffer containing read data.
 | 
						|
  @param  Task                    point to task instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The operation is performed successfully.
 | 
						|
  @retval EFI_VOLUME_CORRUPTED  - The access is
 | 
						|
  @return Others                - The status of read/write the disk
 | 
						|
 | 
						|
**/
 | 
						|
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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_DISK_IO_PROTOCOL  *DiskIo;
 | 
						|
  EFI_DISK_READ         IoFunction;
 | 
						|
  FAT_SUBTASK           *Subtask;
 | 
						|
 | 
						|
  //
 | 
						|
  // Verify the IO is in devices range
 | 
						|
  //
 | 
						|
  Status = EFI_VOLUME_CORRUPTED;
 | 
						|
  if (Offset + BufferSize <= Volume->VolumeSize) {
 | 
						|
    if (CACHE_ENABLED (IoMode)) {
 | 
						|
      //
 | 
						|
      // Access cache
 | 
						|
      //
 | 
						|
      Status = FatAccessCache (Volume, CACHE_TYPE (IoMode), RAW_ACCESS (IoMode), Offset, BufferSize, Buffer, Task);
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Access disk directly
 | 
						|
      //
 | 
						|
      if (Task == NULL) {
 | 
						|
        //
 | 
						|
        // Blocking access
 | 
						|
        //
 | 
						|
        DiskIo     = Volume->DiskIo;
 | 
						|
        IoFunction = (IoMode == ReadDisk) ? DiskIo->ReadDisk : DiskIo->WriteDisk;
 | 
						|
        Status     = IoFunction (DiskIo, Volume->MediaId, Offset, BufferSize, Buffer);
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Non-blocking access
 | 
						|
        //
 | 
						|
        Subtask = AllocateZeroPool (sizeof (*Subtask));
 | 
						|
        if (Subtask == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
        } else {
 | 
						|
          Subtask->Signature  = FAT_SUBTASK_SIGNATURE;
 | 
						|
          Subtask->Task       = Task;
 | 
						|
          Subtask->Write      = (BOOLEAN)(IoMode == WriteDisk);
 | 
						|
          Subtask->Offset     = Offset;
 | 
						|
          Subtask->Buffer     = Buffer;
 | 
						|
          Subtask->BufferSize = BufferSize;
 | 
						|
          Status              = gBS->CreateEvent (
 | 
						|
                                       EVT_NOTIFY_SIGNAL,
 | 
						|
                                       TPL_NOTIFY,
 | 
						|
                                       FatOnAccessComplete,
 | 
						|
                                       Subtask,
 | 
						|
                                       &Subtask->DiskIo2Token.Event
 | 
						|
                                       );
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            InsertTailList (&Task->Subtasks, &Subtask->Link);
 | 
						|
          } else {
 | 
						|
            FreePool (Subtask);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Volume->DiskError = TRUE;
 | 
						|
    DEBUG ((DEBUG_ERROR, "FatDiskIo: error %r\n", Status));
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Lock the volume.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatAcquireLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EfiAcquireLock (&FatFsLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Lock the volume.
 | 
						|
  If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.
 | 
						|
  Otherwise, EFI_SUCCESS is returned.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The volume is locked.
 | 
						|
  @retval EFI_ACCESS_DENIED     - The volume could not be locked because it is already locked.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatAcquireLockOrFail (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EfiAcquireLockOrFail (&FatFsLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Unlock the volume.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatReleaseLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EfiReleaseLock (&FatFsLock);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Free directory entry.
 | 
						|
 | 
						|
  @param  DirEnt                - The directory entry to be freed.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatFreeDirEnt (
 | 
						|
  IN FAT_DIRENT  *DirEnt
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (DirEnt->FileString != NULL) {
 | 
						|
    FreePool (DirEnt->FileString);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (DirEnt);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Free volume structure (including the contents of directory cache and disk cache).
 | 
						|
 | 
						|
  @param  Volume                - The volume structure to be freed.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatFreeVolume (
 | 
						|
  IN FAT_VOLUME  *Volume
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Free disk cache
 | 
						|
  //
 | 
						|
  if (Volume->CacheBuffer != NULL) {
 | 
						|
    FreePool (Volume->CacheBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free directory cache
 | 
						|
  //
 | 
						|
  FatCleanupODirCache (Volume);
 | 
						|
  FreePool (Volume);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Translate EFI time to FAT time.
 | 
						|
 | 
						|
  @param  ETime                 - The time of EFI_TIME.
 | 
						|
  @param  FTime                 - The time of FAT_DATE_TIME.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatEfiTimeToFatTime (
 | 
						|
  IN  EFI_TIME       *ETime,
 | 
						|
  OUT FAT_DATE_TIME  *FTime
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // ignores timezone info in source ETime
 | 
						|
  //
 | 
						|
  if (ETime->Year > 1980) {
 | 
						|
    FTime->Date.Year = (UINT16)(ETime->Year - 1980);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ETime->Year >= 1980 + FAT_MAX_YEAR_FROM_1980) {
 | 
						|
    FTime->Date.Year = FAT_MAX_YEAR_FROM_1980;
 | 
						|
  }
 | 
						|
 | 
						|
  FTime->Date.Month        = ETime->Month;
 | 
						|
  FTime->Date.Day          = ETime->Day;
 | 
						|
  FTime->Time.Hour         = ETime->Hour;
 | 
						|
  FTime->Time.Minute       = ETime->Minute;
 | 
						|
  FTime->Time.DoubleSecond = (UINT16)(ETime->Second / 2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Translate Fat time to EFI time.
 | 
						|
 | 
						|
  @param  FTime                 - The time of FAT_DATE_TIME.
 | 
						|
  @param  ETime                 - The time of EFI_TIME..
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatFatTimeToEfiTime (
 | 
						|
  IN  FAT_DATE_TIME  *FTime,
 | 
						|
  OUT EFI_TIME       *ETime
 | 
						|
  )
 | 
						|
{
 | 
						|
  ETime->Year       = (UINT16)(FTime->Date.Year + 1980);
 | 
						|
  ETime->Month      = (UINT8)FTime->Date.Month;
 | 
						|
  ETime->Day        = (UINT8)FTime->Date.Day;
 | 
						|
  ETime->Hour       = (UINT8)FTime->Time.Hour;
 | 
						|
  ETime->Minute     = (UINT8)FTime->Time.Minute;
 | 
						|
  ETime->Second     = (UINT8)(FTime->Time.DoubleSecond * 2);
 | 
						|
  ETime->Nanosecond = 0;
 | 
						|
  ETime->TimeZone   = EFI_UNSPECIFIED_TIMEZONE;
 | 
						|
  ETime->Daylight   = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get Current FAT time.
 | 
						|
 | 
						|
  @param  FatNow                - Current FAT time.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FatGetCurrentFatTime (
 | 
						|
  OUT FAT_DATE_TIME  *FatNow
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_TIME    Now;
 | 
						|
 | 
						|
  Status = gRT->GetTime (&Now, NULL);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    FatEfiTimeToFatTime (&Now, FatNow);
 | 
						|
  } else {
 | 
						|
    ZeroMem (&Now, sizeof (EFI_TIME));
 | 
						|
    Now.Year  = 1980;
 | 
						|
    Now.Month = 1;
 | 
						|
    Now.Day   = 1;
 | 
						|
    FatEfiTimeToFatTime (&Now, FatNow);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Check whether a time is valid.
 | 
						|
 | 
						|
  @param  Time                  - The time of EFI_TIME.
 | 
						|
 | 
						|
  @retval TRUE                  - The time is valid.
 | 
						|
  @retval FALSE                 - The time is not valid.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
FatIsValidTime (
 | 
						|
  IN EFI_TIME  *Time
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN    Day;
 | 
						|
  BOOLEAN  ValidTime;
 | 
						|
 | 
						|
  ValidTime = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check the fields for range problems
 | 
						|
  // Fat can only support from 1980
 | 
						|
  //
 | 
						|
  if ((Time->Year < 1980) ||
 | 
						|
      (Time->Month < 1) ||
 | 
						|
      (Time->Month > 12) ||
 | 
						|
      (Time->Day < 1) ||
 | 
						|
      (Time->Day > 31) ||
 | 
						|
      (Time->Hour > 23) ||
 | 
						|
      (Time->Minute > 59) ||
 | 
						|
      (Time->Second > 59) ||
 | 
						|
      (Time->Nanosecond > 999999999)
 | 
						|
      )
 | 
						|
  {
 | 
						|
    ValidTime = FALSE;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Perform a more specific check of the day of the month
 | 
						|
    //
 | 
						|
    Day = mMonthDays[Time->Month - 1];
 | 
						|
    if ((Time->Month == 2) && IS_LEAP_YEAR (Time->Year)) {
 | 
						|
      Day += 1;
 | 
						|
      //
 | 
						|
      // 1 extra day this month
 | 
						|
      //
 | 
						|
    }
 | 
						|
 | 
						|
    if (Time->Day > Day) {
 | 
						|
      ValidTime = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ValidTime;
 | 
						|
}
 |