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;
 | |
| }
 |