Home | History | Annotate | Download | only in EnhancedFatDxe
      1 /** @file
      2   Routines dealing with disk spaces and FAT table entries.
      3 
      4 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials are licensed and made available
      6 under the terms and conditions of the BSD License which accompanies this
      7 distribution. The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 
     14 
     15 **/
     16 
     17 #include "Fat.h"
     18 
     19 
     20 /**
     21 
     22   Get the FAT entry of the volume, which is identified with the Index.
     23 
     24   @param  Volume                - FAT file system volume.
     25   @param  Index                 - The index of the FAT entry of the volume.
     26 
     27   @return The buffer of the FAT entry
     28 
     29 **/
     30 STATIC
     31 VOID *
     32 FatLoadFatEntry (
     33   IN FAT_VOLUME       *Volume,
     34   IN UINTN            Index
     35   )
     36 {
     37   UINTN       Pos;
     38   EFI_STATUS  Status;
     39 
     40   if (Index > (Volume->MaxCluster + 1)) {
     41     Volume->FatEntryBuffer = (UINT32) -1;
     42     return &Volume->FatEntryBuffer;
     43   }
     44   //
     45   // Compute buffer position needed
     46   //
     47   switch (Volume->FatType) {
     48   case Fat12:
     49     Pos = FAT_POS_FAT12 (Index);
     50     break;
     51 
     52   case Fat16:
     53     Pos = FAT_POS_FAT16 (Index);
     54     break;
     55 
     56   default:
     57     Pos = FAT_POS_FAT32 (Index);
     58   }
     59   //
     60   // Set the position and read the buffer
     61   //
     62   Volume->FatEntryPos = Volume->FatPos + Pos;
     63   Status = FatDiskIo (
     64              Volume,
     65              ReadFat,
     66              Volume->FatEntryPos,
     67              Volume->FatEntrySize,
     68              &Volume->FatEntryBuffer,
     69              NULL
     70              );
     71   if (EFI_ERROR (Status)) {
     72     Volume->FatEntryBuffer = (UINT32) -1;
     73   }
     74 
     75   return &Volume->FatEntryBuffer;
     76 }
     77 
     78 /**
     79 
     80   Get the FAT entry value of the volume, which is identified with the Index.
     81 
     82   @param  Volume                - FAT file system volume.
     83   @param  Index                 - The index of the FAT entry of the volume.
     84 
     85   @return  The value of the FAT entry.
     86 
     87 **/
     88 STATIC
     89 UINTN
     90 FatGetFatEntry (
     91   IN FAT_VOLUME       *Volume,
     92   IN UINTN            Index
     93   )
     94 {
     95   VOID    *Pos;
     96   UINT8   *En12;
     97   UINT16  *En16;
     98   UINT32  *En32;
     99   UINTN   Accum;
    100 
    101   Pos = FatLoadFatEntry (Volume, Index);
    102 
    103   if (Index > (Volume->MaxCluster + 1)) {
    104     return (UINTN) -1;
    105   }
    106 
    107   switch (Volume->FatType) {
    108   case Fat12:
    109     En12   = Pos;
    110     Accum = En12[0] | (En12[1] << 8);
    111     Accum = FAT_ODD_CLUSTER_FAT12 (Index) ? (Accum >> 4) : (Accum & FAT_CLUSTER_MASK_FAT12);
    112     Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT12) ? FAT_CLUSTER_SPECIAL_EXT : 0);
    113     break;
    114 
    115   case Fat16:
    116     En16   = Pos;
    117     Accum = *En16;
    118     Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT16) ? FAT_CLUSTER_SPECIAL_EXT : 0);
    119     break;
    120 
    121   default:
    122     En32   = Pos;
    123     Accum = *En32 & FAT_CLUSTER_MASK_FAT32;
    124     Accum = Accum | ((Accum >= FAT_CLUSTER_SPECIAL_FAT32) ? FAT_CLUSTER_SPECIAL_EXT : 0);
    125   }
    126 
    127   return Accum;
    128 }
    129 
    130 /**
    131 
    132   Set the FAT entry value of the volume, which is identified with the Index.
    133 
    134   @param  Volume                - FAT file system volume.
    135   @param  Index                 - The index of the FAT entry of the volume.
    136   @param  Value                 - The new value of the FAT entry.
    137 
    138   @retval EFI_SUCCESS           - Set the new FAT entry value sucessfully.
    139   @retval EFI_VOLUME_CORRUPTED  - The FAT type of the volume is error.
    140   @return other                 - An error occurred when operation the FAT entries.
    141 
    142 **/
    143 STATIC
    144 EFI_STATUS
    145 FatSetFatEntry (
    146   IN FAT_VOLUME       *Volume,
    147   IN UINTN            Index,
    148   IN UINTN            Value
    149   )
    150 {
    151   VOID        *Pos;
    152   UINT8       *En12;
    153   UINT16      *En16;
    154   UINT32      *En32;
    155   UINTN       Accum;
    156   EFI_STATUS  Status;
    157   UINTN       OriginalVal;
    158 
    159   if (Index < FAT_MIN_CLUSTER) {
    160     return EFI_VOLUME_CORRUPTED;
    161   }
    162 
    163   OriginalVal = FatGetFatEntry (Volume, Index);
    164   if (Value == FAT_CLUSTER_FREE && OriginalVal != FAT_CLUSTER_FREE) {
    165     Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
    166     if (Index < Volume->FatInfoSector.FreeInfo.NextCluster) {
    167       Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
    168     }
    169   } else if (Value != FAT_CLUSTER_FREE && OriginalVal == FAT_CLUSTER_FREE) {
    170     if (Volume->FatInfoSector.FreeInfo.ClusterCount != 0) {
    171       Volume->FatInfoSector.FreeInfo.ClusterCount -= 1;
    172     }
    173   }
    174   //
    175   // Make sure the entry is in memory
    176   //
    177   Pos = FatLoadFatEntry (Volume, Index);
    178 
    179   //
    180   // Update the value
    181   //
    182   switch (Volume->FatType) {
    183   case Fat12:
    184     En12   = Pos;
    185     Accum = En12[0] | (En12[1] << 8);
    186     Value = Value & FAT_CLUSTER_MASK_FAT12;
    187 
    188     if (FAT_ODD_CLUSTER_FAT12 (Index)) {
    189       Accum = (Value << 4) | (Accum & 0xF);
    190     } else {
    191       Accum = Value | (Accum & FAT_CLUSTER_UNMASK_FAT12);
    192     }
    193 
    194     En12[0]  = (UINT8) (Accum & 0xFF);
    195     En12[1]  = (UINT8) (Accum >> 8);
    196     break;
    197 
    198   case Fat16:
    199     En16   = Pos;
    200     *En16  = (UINT16) Value;
    201     break;
    202 
    203   default:
    204     En32   = Pos;
    205     *En32  = (*En32 & FAT_CLUSTER_UNMASK_FAT32) | (UINT32) (Value & FAT_CLUSTER_MASK_FAT32);
    206   }
    207   //
    208   // If the volume's dirty bit is not set, set it now
    209   //
    210   if (!Volume->FatDirty && Volume->FatType != Fat12) {
    211     Volume->FatDirty = TRUE;
    212     FatAccessVolumeDirty (Volume, WriteFat, &Volume->DirtyValue);
    213   }
    214   //
    215   // Write the updated fat entry value to the volume
    216   // The fat is the first fat, and other fat will be in sync
    217   // when the FAT cache flush back.
    218   //
    219   Status = FatDiskIo (
    220              Volume,
    221              WriteFat,
    222              Volume->FatEntryPos,
    223              Volume->FatEntrySize,
    224              &Volume->FatEntryBuffer,
    225              NULL
    226              );
    227   return Status;
    228 }
    229 
    230 /**
    231 
    232   Free the cluster clain.
    233 
    234   @param  Volume                - FAT file system volume.
    235   @param  Cluster               - The first cluster of cluster chain.
    236 
    237   @retval EFI_SUCCESS           - The cluster chain is freed successfully.
    238   @retval EFI_VOLUME_CORRUPTED  - There are errors in the file's clusters.
    239 
    240 **/
    241 STATIC
    242 EFI_STATUS
    243 FatFreeClusters (
    244   IN FAT_VOLUME           *Volume,
    245   IN UINTN                Cluster
    246   )
    247 {
    248   UINTN LastCluster;
    249 
    250   while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
    251     if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
    252 
    253       DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
    254       return EFI_VOLUME_CORRUPTED;
    255     }
    256 
    257     LastCluster = Cluster;
    258     Cluster     = FatGetFatEntry (Volume, Cluster);
    259     FatSetFatEntry (Volume, LastCluster, FAT_CLUSTER_FREE);
    260   }
    261 
    262   return EFI_SUCCESS;
    263 }
    264 
    265 /**
    266 
    267   Allocate a free cluster and return the cluster index.
    268 
    269   @param  Volume                - FAT file system volume.
    270 
    271   @return The index of the free cluster
    272 
    273 **/
    274 STATIC
    275 UINTN
    276 FatAllocateCluster (
    277   IN FAT_VOLUME   *Volume
    278   )
    279 {
    280   UINTN Cluster;
    281 
    282   //
    283   // Start looking at FatFreePos for the next unallocated cluster
    284   //
    285   if (Volume->DiskError) {
    286     return (UINTN) FAT_CLUSTER_LAST;
    287   }
    288 
    289   for (;;) {
    290     //
    291     // If the end of the list, return no available cluster
    292     //
    293     if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
    294       if (Volume->FreeInfoValid && 0 < (INT32) (Volume->FatInfoSector.FreeInfo.ClusterCount)) {
    295         Volume->FreeInfoValid = FALSE;
    296       }
    297 
    298       FatComputeFreeInfo (Volume);
    299       if (Volume->FatInfoSector.FreeInfo.NextCluster > (Volume->MaxCluster + 1)) {
    300         return (UINTN) FAT_CLUSTER_LAST;
    301       }
    302     }
    303 
    304     Cluster = FatGetFatEntry (Volume, Volume->FatInfoSector.FreeInfo.NextCluster);
    305     if (Cluster == FAT_CLUSTER_FREE) {
    306       break;
    307     }
    308     //
    309     // Try the next cluster
    310     //
    311     Volume->FatInfoSector.FreeInfo.NextCluster += 1;
    312   }
    313 
    314   Cluster = Volume->FatInfoSector.FreeInfo.NextCluster;
    315   Volume->FatInfoSector.FreeInfo.NextCluster += 1;
    316   return Cluster;
    317 }
    318 
    319 /**
    320 
    321   Count the number of clusters given a size.
    322 
    323   @param  Volume                - The file system volume.
    324   @param  Size                  - The size in bytes.
    325 
    326   @return The number of the clusters.
    327 
    328 **/
    329 STATIC
    330 UINTN
    331 FatSizeToClusters (
    332   IN FAT_VOLUME       *Volume,
    333   IN UINTN            Size
    334   )
    335 {
    336   UINTN Clusters;
    337 
    338   Clusters = Size >> Volume->ClusterAlignment;
    339   if ((Size & (Volume->ClusterSize - 1)) > 0) {
    340     Clusters += 1;
    341   }
    342 
    343   return Clusters;
    344 }
    345 
    346 /**
    347 
    348   Shrink the end of the open file base on the file size.
    349 
    350   @param  OFile                 - The open file.
    351 
    352   @retval EFI_SUCCESS           - Shrinked sucessfully.
    353   @retval EFI_VOLUME_CORRUPTED  - There are errors in the file's clusters.
    354 
    355 **/
    356 EFI_STATUS
    357 FatShrinkEof (
    358   IN FAT_OFILE            *OFile
    359   )
    360 {
    361   FAT_VOLUME  *Volume;
    362   UINTN       NewSize;
    363   UINTN       CurSize;
    364   UINTN       Cluster;
    365   UINTN       LastCluster;
    366 
    367   Volume  = OFile->Volume;
    368   ASSERT_VOLUME_LOCKED (Volume);
    369 
    370   NewSize = FatSizeToClusters (Volume, OFile->FileSize);
    371 
    372   //
    373   // Find the address of the last cluster
    374   //
    375   Cluster     = OFile->FileCluster;
    376   LastCluster = FAT_CLUSTER_FREE;
    377 
    378   if (NewSize != 0) {
    379 
    380     for (CurSize = 0; CurSize < NewSize; CurSize++) {
    381       if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
    382 
    383         DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatShrinkEof: cluster chain corrupt\n"));
    384         return EFI_VOLUME_CORRUPTED;
    385       }
    386 
    387       LastCluster = Cluster;
    388       Cluster     = FatGetFatEntry (Volume, Cluster);
    389     }
    390 
    391     FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
    392 
    393   } else {
    394     //
    395     // Check to see if the file is already completely truncated
    396     //
    397     if (Cluster == FAT_CLUSTER_FREE) {
    398       return EFI_SUCCESS;
    399     }
    400     //
    401     // The file is being completely truncated.
    402     //
    403     OFile->FileCluster      = FAT_CLUSTER_FREE;
    404   }
    405   //
    406   // Set CurrentCluster == FileCluster
    407   // to force a recalculation of Position related stuffs
    408   //
    409   OFile->FileCurrentCluster = OFile->FileCluster;
    410   OFile->FileLastCluster    = LastCluster;
    411   OFile->Dirty              = TRUE;
    412   //
    413   // Free the remaining cluster chain
    414   //
    415   return FatFreeClusters (Volume, Cluster);
    416 }
    417 
    418 /**
    419 
    420   Grow the end of the open file base on the NewSizeInBytes.
    421 
    422   @param  OFile                 - The open file.
    423   @param  NewSizeInBytes        - The new size in bytes of the open file.
    424 
    425   @retval EFI_SUCCESS           - The file is grown sucessfully.
    426   @retval EFI_UNSUPPORTED       - The file size is larger than 4GB.
    427   @retval EFI_VOLUME_CORRUPTED  - There are errors in the files' clusters.
    428   @retval EFI_VOLUME_FULL       - The volume is full and can not grow the file.
    429 
    430 **/
    431 EFI_STATUS
    432 FatGrowEof (
    433   IN FAT_OFILE            *OFile,
    434   IN UINT64               NewSizeInBytes
    435   )
    436 {
    437   FAT_VOLUME  *Volume;
    438   EFI_STATUS  Status;
    439   UINTN       Cluster;
    440   UINTN       CurSize;
    441   UINTN       NewSize;
    442   UINTN       LastCluster;
    443   UINTN       NewCluster;
    444   UINTN       ClusterCount;
    445 
    446   //
    447   // For FAT file system, the max file is 4GB.
    448   //
    449   if (NewSizeInBytes > 0x0FFFFFFFFL) {
    450     return EFI_UNSUPPORTED;
    451   }
    452 
    453   Volume = OFile->Volume;
    454   ASSERT_VOLUME_LOCKED (Volume);
    455   //
    456   // If the file is already large enough, do nothing
    457   //
    458   CurSize = FatSizeToClusters (Volume, OFile->FileSize);
    459   NewSize = FatSizeToClusters (Volume, (UINTN) NewSizeInBytes);
    460 
    461   if (CurSize < NewSize) {
    462     //
    463     // If we haven't found the files last cluster do it now
    464     //
    465     if ((OFile->FileCluster != 0) && (OFile->FileLastCluster == 0)) {
    466       Cluster       = OFile->FileCluster;
    467       ClusterCount  = 0;
    468 
    469       while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
    470         if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
    471 
    472           DEBUG (
    473             (EFI_D_INIT | EFI_D_ERROR,
    474             "FatGrowEof: cluster chain corrupt\n")
    475             );
    476           Status = EFI_VOLUME_CORRUPTED;
    477           goto Done;
    478         }
    479 
    480         ClusterCount++;
    481         OFile->FileLastCluster  = Cluster;
    482         Cluster                 = FatGetFatEntry (Volume, Cluster);
    483       }
    484 
    485       if (ClusterCount != CurSize) {
    486         DEBUG (
    487           (EFI_D_INIT | EFI_D_ERROR,
    488           "FatGrowEof: cluster chain size does not match file size\n")
    489           );
    490         Status = EFI_VOLUME_CORRUPTED;
    491         goto Done;
    492       }
    493 
    494     }
    495     //
    496     // Loop until we've allocated enough space
    497     //
    498     LastCluster = OFile->FileLastCluster;
    499 
    500     while (CurSize < NewSize) {
    501       NewCluster = FatAllocateCluster (Volume);
    502       if (FAT_END_OF_FAT_CHAIN (NewCluster)) {
    503         if (LastCluster != FAT_CLUSTER_FREE) {
    504           FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
    505           OFile->FileLastCluster = LastCluster;
    506         }
    507 
    508         Status = EFI_VOLUME_FULL;
    509         goto Done;
    510       }
    511 
    512       if (LastCluster != 0) {
    513         FatSetFatEntry (Volume, LastCluster, NewCluster);
    514       } else {
    515         OFile->FileCluster        = NewCluster;
    516         OFile->FileCurrentCluster = NewCluster;
    517       }
    518 
    519       LastCluster = NewCluster;
    520       CurSize += 1;
    521     }
    522     //
    523     // Terminate the cluster list
    524     //
    525     FatSetFatEntry (Volume, LastCluster, (UINTN) FAT_CLUSTER_LAST);
    526     OFile->FileLastCluster = LastCluster;
    527   }
    528 
    529   OFile->FileSize = (UINTN) NewSizeInBytes;
    530   OFile->Dirty    = TRUE;
    531   return EFI_SUCCESS;
    532 
    533 Done:
    534   FatShrinkEof (OFile);
    535   return Status;
    536 }
    537 
    538 /**
    539 
    540   Seek OFile to requested position, and calculate the number of
    541   consecutive clusters from the position in the file
    542 
    543   @param  OFile                 - The open file.
    544   @param  Position              - The file's position which will be accessed.
    545   @param  PosLimit              - The maximum length current reading/writing may access
    546 
    547   @retval EFI_SUCCESS           - Set the info successfully.
    548   @retval EFI_VOLUME_CORRUPTED  - Cluster chain corrupt.
    549 
    550 **/
    551 EFI_STATUS
    552 FatOFilePosition (
    553   IN FAT_OFILE            *OFile,
    554   IN UINTN                Position,
    555   IN UINTN                PosLimit
    556   )
    557 {
    558   FAT_VOLUME  *Volume;
    559   UINTN       ClusterSize;
    560   UINTN       Cluster;
    561   UINTN       StartPos;
    562   UINTN       Run;
    563 
    564   Volume      = OFile->Volume;
    565   ClusterSize = Volume->ClusterSize;
    566 
    567   ASSERT_VOLUME_LOCKED (Volume);
    568 
    569   //
    570   // If this is the fixed root dir, then compute it's position
    571   // from it's fixed info in the fat bpb
    572   //
    573   if (OFile->IsFixedRootDir) {
    574     OFile->PosDisk  = Volume->RootPos + Position;
    575     Run             = OFile->FileSize - Position;
    576   } else {
    577     //
    578     // Run the file's cluster chain to find the current position
    579     // If possible, run from the current cluster rather than
    580     // start from beginning
    581     // Assumption: OFile->Position is always consistent with
    582     // OFile->FileCurrentCluster.
    583     // OFile->Position is not modified outside this function;
    584     // OFile->FileCurrentCluster is modified outside this function
    585     // to be the same as OFile->FileCluster
    586     // when OFile->FileCluster is updated, so make a check of this
    587     // and invalidate the original OFile->Position in this case
    588     //
    589     Cluster     = OFile->FileCurrentCluster;
    590     StartPos    = OFile->Position;
    591     if (Position < StartPos || OFile->FileCluster == Cluster) {
    592       StartPos  = 0;
    593       Cluster   = OFile->FileCluster;
    594     }
    595 
    596     while (StartPos + ClusterSize <= Position) {
    597       StartPos += ClusterSize;
    598       if (Cluster == FAT_CLUSTER_FREE || (Cluster >= FAT_CLUSTER_SPECIAL)) {
    599         DEBUG ((EFI_D_INIT | EFI_D_ERROR, "FatOFilePosition:"" cluster chain corrupt\n"));
    600         return EFI_VOLUME_CORRUPTED;
    601       }
    602 
    603       Cluster = FatGetFatEntry (Volume, Cluster);
    604     }
    605 
    606     if (Cluster < FAT_MIN_CLUSTER) {
    607       return EFI_VOLUME_CORRUPTED;
    608     }
    609 
    610     OFile->PosDisk            = Volume->FirstClusterPos +
    611                                 LShiftU64 (Cluster - FAT_MIN_CLUSTER, Volume->ClusterAlignment) +
    612                                 Position - StartPos;
    613     OFile->FileCurrentCluster = Cluster;
    614     OFile->Position           = StartPos;
    615 
    616     //
    617     // Compute the number of consecutive clusters in the file
    618     //
    619     Run = StartPos + ClusterSize - Position;
    620     if (!FAT_END_OF_FAT_CHAIN (Cluster)) {
    621       while ((FatGetFatEntry (Volume, Cluster) == Cluster + 1) && Run < PosLimit) {
    622         Run     += ClusterSize;
    623         Cluster += 1;
    624       }
    625     }
    626   }
    627 
    628   OFile->PosRem = Run;
    629   return EFI_SUCCESS;
    630 }
    631 
    632 /**
    633 
    634   Get the size of directory of the open file.
    635 
    636   @param  Volume                - The File System Volume.
    637   @param  Cluster               - The Starting cluster.
    638 
    639   @return The physical size of the file starting at the input cluster, if there is error in the
    640   cluster chain, the return value is 0.
    641 
    642 **/
    643 UINTN
    644 FatPhysicalDirSize (
    645   IN FAT_VOLUME            *Volume,
    646   IN UINTN                 Cluster
    647   )
    648 {
    649   UINTN Size;
    650   ASSERT_VOLUME_LOCKED (Volume);
    651   //
    652   // Run the cluster chain for the OFile
    653   //
    654   Size = 0;
    655   //
    656   // N.B. ".." directories on some media do not contain a starting
    657   // cluster.  In the case of "." or ".." we don't need the size anyway.
    658   //
    659   if (Cluster != 0) {
    660     while (!FAT_END_OF_FAT_CHAIN (Cluster)) {
    661       if (Cluster == FAT_CLUSTER_FREE || Cluster >= FAT_CLUSTER_SPECIAL) {
    662         DEBUG (
    663           (EFI_D_INIT | EFI_D_ERROR,
    664           "FATDirSize: cluster chain corrupt\n")
    665           );
    666         return 0;
    667       }
    668 
    669       Size += Volume->ClusterSize;
    670       Cluster = FatGetFatEntry (Volume, Cluster);
    671     }
    672   }
    673 
    674   return Size;
    675 }
    676 
    677 /**
    678 
    679   Get the physical size of a file on the disk.
    680 
    681   @param  Volume                - The file system volume.
    682   @param  RealSize              - The real size of a file.
    683 
    684   @return The physical size of a file on the disk.
    685 
    686 **/
    687 UINT64
    688 FatPhysicalFileSize (
    689   IN FAT_VOLUME            *Volume,
    690   IN UINTN                 RealSize
    691   )
    692 {
    693   UINTN   ClusterSizeMask;
    694   UINT64  PhysicalSize;
    695   ClusterSizeMask = Volume->ClusterSize - 1;
    696   PhysicalSize    = (RealSize + ClusterSizeMask) & (~((UINT64) ClusterSizeMask));
    697   return PhysicalSize;
    698 }
    699 
    700 /**
    701 
    702   Update the free cluster info of FatInfoSector of the volume.
    703 
    704   @param  Volume                - FAT file system volume.
    705 
    706 **/
    707 VOID
    708 FatComputeFreeInfo (
    709   IN FAT_VOLUME *Volume
    710   )
    711 {
    712   UINTN Index;
    713 
    714   //
    715   // If we don't have valid info, compute it now
    716   //
    717   if (!Volume->FreeInfoValid) {
    718 
    719     Volume->FreeInfoValid                        = TRUE;
    720     Volume->FatInfoSector.FreeInfo.ClusterCount  = 0;
    721     for (Index = Volume->MaxCluster + 1; Index >= FAT_MIN_CLUSTER; Index--) {
    722       if (Volume->DiskError) {
    723         break;
    724       }
    725 
    726       if (FatGetFatEntry (Volume, Index) == FAT_CLUSTER_FREE) {
    727         Volume->FatInfoSector.FreeInfo.ClusterCount += 1;
    728         Volume->FatInfoSector.FreeInfo.NextCluster = (UINT32) Index;
    729       }
    730     }
    731 
    732     Volume->FatInfoSector.Signature          = FAT_INFO_SIGNATURE;
    733     Volume->FatInfoSector.InfoBeginSignature = FAT_INFO_BEGIN_SIGNATURE;
    734     Volume->FatInfoSector.InfoEndSignature   = FAT_INFO_END_SIGNATURE;
    735   }
    736 }
    737