userlibandfileserver/fileserver/sfat32/sl_fatmisc32.cpp
changeset 90 947f0dc9f7a8
parent 0 a41df078684a
child 269 d57b86b1867a
equal deleted inserted replaced
52:2d65c2f76d7b 90:947f0dc9f7a8
    37 /**
    37 /**
    38 Calculate the FAT size in sectors for a Fat32 volume
    38 Calculate the FAT size in sectors for a Fat32 volume
    39 
    39 
    40 @return The number of sectors
    40 @return The number of sectors
    41 */
    41 */
    42 TUint32 CFatFormatCB::MaxFat32Sectors() const
    42 TUint CFatFormatCB::MaxFat32Sectors() const
    43 	{
    43 	{
    44 	TUint32 calc1 = iMaxDiskSectors - iReservedSectors;
    44 	TUint32 calc1 = iMaxDiskSectors - iReservedSectors;
    45 	TUint32 calc2 = (256 * iSectorsPerCluster) + iNumberOfFats;
    45 	TUint32 calc2 = (256 * iSectorsPerCluster) + iNumberOfFats;
    46 	calc2 = calc2 >> 1;
    46 	calc2 = calc2 >> 1;
    47 	return (calc1 + (calc2 - 1))/calc2;
    47 	return ((calc1 + (calc2 - 1))/calc2);
    48 	}
    48 	}
    49 
    49 
    50 
    50 
    51 const TUint KDefFatResvdSec = 1;    ///< default number of FAT12/16 reserved sectors
    51 const TUint KDefFatResvdSec = 1;    ///< default number of FAT12/16 reserved sectors
    52 const TUint KDefFat32ResvdSec = 32; ///< default number of FAT32 reserved sectors
    52 const TUint KDefFat32ResvdSec = 32; ///< default number of FAT32 reserved sectors
    74 Setting set to adhere to Rules of Count of clusters for FAT type
    74 Setting set to adhere to Rules of Count of clusters for FAT type
    75 
    75 
    76 @param  aDiskSizeInSectors Size of volume in sectors
    76 @param  aDiskSizeInSectors Size of volume in sectors
    77 @return system-wide error code
    77 @return system-wide error code
    78 */
    78 */
    79 TInt  CFatFormatCB::InitFormatDataForFixedSizeDiskNormal(TInt aDiskSizeInSectors, const TLocalDriveCapsV6& aCaps)
    79 TInt  CFatFormatCB::InitFormatDataForFixedSizeDiskNormal(TUint aDiskSizeInSectors, const TLocalDriveCapsV6& aCaps)
    80 	{
    80 	{
    81 	__PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskNormal() sectors:%d"), aDiskSizeInSectors);
    81 	__PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskNormal() sectors:%d"), aDiskSizeInSectors);
    82     
    82     
    83     if( Drive().IsRemovable() )
    83     if( Drive().IsRemovable() )
    84 		iNumberOfFats = KNumberOfFatsExternal;
    84 		iNumberOfFats = KNumberOfFatsExternal;
   115 		iSectorsPerFat=MaxFat12Sectors();
   115 		iSectorsPerFat=MaxFat12Sectors();
   116 		}
   116 		}
   117 	else if(aDiskSizeInSectors<1048576) // >= 16Mb - FAT16   < (1048576) 512MB
   117 	else if(aDiskSizeInSectors<1048576) // >= 16Mb - FAT16   < (1048576) 512MB
   118 		{
   118 		{
   119 		iFileSystemName=KFileSystemName16;
   119 		iFileSystemName=KFileSystemName16;
   120 		TInt minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
   120 		TUint minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
   121 		iRootDirEntries=512;
   121 		iRootDirEntries=512;
   122 		iSectorsPerCluster=1;
   122 		iSectorsPerCluster=1;
       
   123 		
   123 		while (minSectorsPerCluster>iSectorsPerCluster)
   124 		while (minSectorsPerCluster>iSectorsPerCluster)
   124 			iSectorsPerCluster<<=1;
   125 			iSectorsPerCluster<<=1;
       
   126 
   125 		iSectorsPerFat=MaxFat16Sectors();
   127 		iSectorsPerFat=MaxFat16Sectors();
   126 		}
   128 		}
   127 	else	//use FAT32
   129 	else	//use FAT32
   128 		{
   130 		{
   129 		iFileSystemName=KFileSystemName32;
   131 		iFileSystemName=KFileSystemName32;
   140 		iRootClusterNum=2;						//As recomended in the document
   142 		iRootClusterNum=2;						//As recomended in the document
   141 		iSectorsPerFat=MaxFat32Sectors();
   143 		iSectorsPerFat=MaxFat32Sectors();
   142 		
   144 		
   143 		}
   145 		}
   144 
   146 
       
   147 	const TFatType fatType = SuggestFatType();
       
   148 
   145 	// Ensure cluster size is a multiple of the block size
   149 	// Ensure cluster size is a multiple of the block size
   146 	TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2;
   150 	TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2;
   147 	__PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors);
   151 	__PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors);
   148 	ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors));
   152 	ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors));
   149 	if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors))
   153 	if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors))
   150 		{
   154 		{
   151 		__PRINT1(_L("iSectorsPerCluster	(old): %d"),iSectorsPerCluster);
   155 		__PRINT1(_L("iSectorsPerCluster    (old): %d"),iSectorsPerCluster);
   152 		AdjustClusterSize(blockSizeInSectors);
   156 		AdjustClusterSize(blockSizeInSectors);
   153 		__PRINT1(_L("iSectorsPerCluster	(new): %d"),iSectorsPerCluster);
   157 		__PRINT1(_L("iSectorsPerCluster    (new): %d"),iSectorsPerCluster);
   154 		}
   158 		}
   155 
   159 
   156 	// Align first data sector on an erase block boundary if
   160 
   157 	// (1) the iEraseBlockSize is specified
   161 	for (; iSectorsPerCluster>1; iSectorsPerCluster>>= 1)
   158 	// (2) the start of the partition is already aligned to an erase block boundary, 
   162 		{
   159 	//     i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize
   163 		// Align first data sector on an erase block boundary if
   160 	__PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors);
   164 		// (1) the iEraseBlockSize is specified
   161 	TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2;
   165 		// (2) the start of the partition is already aligned to an erase block boundary, 
   162 	__PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors);
   166 		//     i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize
   163 	ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors));	
   167 		__PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors);
   164 	ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors);
   168 		TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2;
   165 	if ((eraseblockSizeInSectors != 0) &&
   169 		__PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors);
   166 		(iHiddenSectors % eraseblockSizeInSectors == 0) &&	
   170 		ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors));	
   167 		(IsPowerOf2(eraseblockSizeInSectors)) &&
   171 		ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors);
   168 		(eraseblockSizeInSectors >= blockSizeInSectors))
   172 		if ((eraseblockSizeInSectors != 0) &&
   169 		{
   173 			(iHiddenSectors % eraseblockSizeInSectors == 0) &&	
   170 		TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors);
   174 			(IsPowerOf2(eraseblockSizeInSectors)) &&
   171 		ASSERT(r == KErrNone);
   175 			(eraseblockSizeInSectors >= blockSizeInSectors))
   172 		(void) r;
   176 			{
   173 		}
   177 			TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors);
   174 	__PRINT1(_L("iReservedSectors: %d"),iReservedSectors);
   178 			ASSERT(r == KErrNone);
   175 	__PRINT1(_L("FirstDataSector: %d"), FirstDataSector());
   179 			(void) r;
       
   180 			}
       
   181 		__PRINT1(_L("iReservedSectors: %d"),iReservedSectors);
       
   182 		__PRINT1(_L("FirstDataSector: %d"), FirstDataSector());
       
   183 
       
   184 		// If we've shrunk the number of clusters by so much that it's now invalid for this FAT type
       
   185 		// then we need to decrease the cluster size and try again, otherwise we're finshed.
       
   186 		if (SuggestFatType() == fatType)
       
   187 			break;
       
   188 		}
       
   189 	__PRINT1(_L("iSectorsPerCluster  (final): %d"),iSectorsPerCluster);
   176 
   190 
   177     return KErrNone;
   191     return KErrNone;
   178 	}
   192 	}
   179 
   193 
   180 TInt CFatFormatCB::FirstDataSector() const
   194 TInt CFatFormatCB::FirstDataSector() const
   181 	{
   195 	{
   182 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   196 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   183     return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
   197     return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors;
   184 	}
   198 	}
   185 
   199 
   186 void CFatFormatCB::AdjustClusterSize(TInt aRecommendedSectorsPerCluster)
   200 void CFatFormatCB::AdjustClusterSize(TUint aRecommendedSectorsPerCluster)
   187 	{
   201 	{
   188     const TInt KMaxSecPerCluster = 64;	// 32K
   202     const TUint KMaxSecPerCluster = 64;	// 32K
       
   203 
   189 	while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
   204 	while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2))
   190 		iSectorsPerCluster<<= 1;
   205 		iSectorsPerCluster<<= 1;
       
   206 
   191 	}
   207 	}
   192 
   208 
   193 // AdjustFirstDataSectorAlignment()
   209 // AdjustFirstDataSectorAlignment()
   194 // Attempts to align the first data sector on an erase block boundary by modifying the
   210 // Attempts to align the first data sector on an erase block boundary by modifying the
   195 // number of reserved sectors.
   211 // number of reserved sectors.
   196 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TInt aEraseBlockSizeInSectors)
   212 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TUint aEraseBlockSizeInSectors)
   197 	{
   213 	{
   198 	const TBool bFat16 = Is16BitFat();
   214 	const TBool bFat16 = Is16BitFat();
   199     const TBool bFat32 = Is32BitFat();
   215     const TBool bFat32 = Is32BitFat();
   200 
   216 
   201 	// Save these 2 values in the event of a convergence failure; this should 
   217 	// Save these 2 values in the event of a convergence failure; this should 
   202 	// hopefully never happen, but we will cater for this in release mode to be safe,
   218 	// hopefully never happen, but we will cater for this in release mode to be safe,
   203 	TInt reservedSectorsSaved = iReservedSectors;
   219 	TUint reservedSectorsSaved = iReservedSectors;
   204 	TInt sectorsPerFatSaved = iSectorsPerFat;
   220 	TUint sectorsPerFatSaved = iSectorsPerFat;
   205 
   221 
   206 	TInt reservedSectorsOld = 0;
   222 	TUint reservedSectorsOld = 0;
   207 
   223 
   208 	// zero for FAT32
   224 	// zero for FAT32
   209 	TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   225 	TUint rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   210 	TInt fatSectors = 0;
   226 	TUint fatSectors = 0;
   211 
   227 
   212 	TInt KMaxIterations = 10;
   228 	TUint KMaxIterations = 10;
   213 	TInt n;
   229 	TUint n;
   214 	for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
   230 	for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++)
   215 		{
   231 		{
   216 		reservedSectorsOld = iReservedSectors;
   232 		reservedSectorsOld = iReservedSectors;
   217 
   233 
   218 		iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
   234 		iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors();
   223 		TInt  nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
   239 		TInt  nBlocks = (iReservedSectors + fatSectors + rootDirSectors + aEraseBlockSizeInSectors-1) / aEraseBlockSizeInSectors;
   224 
   240 
   225 		iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
   241 		iReservedSectors = (nBlocks * aEraseBlockSizeInSectors) - rootDirSectors - fatSectors;
   226 		}
   242 		}
   227 	
   243 	
   228 	ASSERT(iReservedSectors >= (TInt) (bFat32 ? KDefFat32ResvdSec : KDefFatResvdSec));
   244 	ASSERT(iReservedSectors >= (bFat32 ? KDefFat32ResvdSec : KDefFatResvdSec));
   229 
   245 
   230 	if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
   246 	if ((FirstDataSector() & (aEraseBlockSizeInSectors-1)) == 0)
   231 		{
   247 		{
   232 		return KErrNone;
   248 		return KErrNone;
   233 		}
   249 		}
   300 		{
   316 		{
   301 		bootSector.SetFatSectors32(0);
   317 		bootSector.SetFatSectors32(0);
   302 		bootSector.SetFatSectors(iSectorsPerFat);
   318 		bootSector.SetFatSectors(iSectorsPerFat);
   303 		bootSector.SetRootDirEntries(iRootDirEntries);
   319 		bootSector.SetRootDirEntries(iRootDirEntries);
   304 
   320 
   305 		if (iMaxDiskSectors<=(TInt)KMaxTUint16)
   321 		if (iMaxDiskSectors<=KMaxTUint16)
   306 			{
   322 			{
   307 			bootSector.SetTotalSectors(iMaxDiskSectors);
   323 			bootSector.SetTotalSectors(iMaxDiskSectors);
   308 			bootSector.SetHugeSectors(0);
   324 			bootSector.SetHugeSectors(0);
   309 			}
   325 			}
   310 		else
   326 		else
   554     Initialize the user specific format parameters for fixed sized disk.
   570     Initialize the user specific format parameters for fixed sized disk.
   555     
   571     
   556     @param  aDiskSizeInSectors disk size in sectors
   572     @param  aDiskSizeInSectors disk size in sectors
   557     @return system-wide error code
   573     @return system-wide error code
   558 */
   574 */
   559 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TInt aDiskSizeInSectors)
   575 TInt CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TUint aDiskSizeInSectors)
   560 	{
   576 	{
   561     __PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() sectors:%d"), aDiskSizeInSectors);
   577     __PRINT1(_L("CFatFormatCB::InitFormatDataForFixedSizeDiskUser() sectors:%d"), aDiskSizeInSectors);
   562     Dump_TLDFormatInfo(iSpecialInfo());
   578     Dump_TLDFormatInfo(iSpecialInfo());
   563 
   579 
   564     //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
   580     //-- KErrArgument will be returned if iSpecialInfo().iFATBits isn't one of EFB32, EFB16, EFB32
   577         iReservedSectors = KDefFatResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT12/16)
   593         iReservedSectors = KDefFatResvdSec; //-- user hasn't specified reserved sectors count, use default (FAT12/16)
   578     else
   594     else
   579         iReservedSectors = iSpecialInfo().iReservedSectors;
   595         iReservedSectors = iSpecialInfo().iReservedSectors;
   580 
   596 
   581 
   597 
   582     const TInt KMaxSecPerCluster    = 64; 
   598     const TUint KMaxSecPerCluster    = 64; 
   583 	const TInt KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
   599 	const TUint KDefaultSecPerCluster= 8;   //-- default value, if the iSpecialInfo().iSectorsPerCluster isn't specified
   584 
   600 
   585     iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
   601     iSectorsPerCluster = iSpecialInfo().iSectorsPerCluster;
   586     if(iSectorsPerCluster <= 0)
   602     if(iSectorsPerCluster <= 0)
   587         {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
   603         {//-- default value, user hasn't specified TLDFormatInfo::iSectorsPerCluster
   588         iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
   604         iSectorsPerCluster = KDefaultSecPerCluster; //-- will be adjusted later
   599         iSectorsPerCluster = 1;
   615         iSectorsPerCluster = 1;
   600 		iRootDirEntries = 128;
   616 		iRootDirEntries = 128;
   601         }
   617         }
   602 	else if (aDiskSizeInSectors < 8192) // < 4MB
   618 	else if (aDiskSizeInSectors < 8192) // < 4MB
   603         {
   619         {
   604         iSectorsPerCluster = Min(iSectorsPerCluster, 2);
   620         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)2);
   605 		iRootDirEntries = 256;
   621 		iRootDirEntries = 256;
   606         }
   622         }
   607 	else if (aDiskSizeInSectors < 32768) // < 16MB
   623 	else if (aDiskSizeInSectors < 32768) // < 16MB
   608         {
   624         {
   609         iSectorsPerCluster = Min(iSectorsPerCluster, 4);
   625         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)4);
   610 		iRootDirEntries = 512;
   626 		iRootDirEntries = 512;
   611         }
   627         }
   612 	else if (aDiskSizeInSectors < 1048576) // < 512MB
   628 	else if (aDiskSizeInSectors < 1048576) // < 512MB
   613         {
   629         {
   614         iSectorsPerCluster = Min(iSectorsPerCluster, 8);
   630         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)8);
   615 		iRootDirEntries = 512;
   631 		iRootDirEntries = 512;
   616         }
   632         }
   617     else // FAT32
   633     else // FAT32
   618 		{
   634 		{
   619         iRootDirEntries = 512;
   635         iRootDirEntries = 512;
   620         iSectorsPerCluster = Min(iSectorsPerCluster, KMaxSecPerCluster);
   636         iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)KMaxSecPerCluster);
   621         }
   637         }
   622 
   638 
   623 
   639 
   624     //-----------------------------------------
   640     //-----------------------------------------
   625 
   641 
   805     TInt sizeofFatAndRootDir;
   821     TInt sizeofFatAndRootDir;
   806     if (iFileSystemName != KFileSystemName32)
   822     if (iFileSystemName != KFileSystemName32)
   807 		sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
   823 		sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2);
   808     else
   824     else
   809         sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster;
   825         sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster;
   810     TInt firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
   826 
       
   827     TUint firstFreeSector = iReservedSectors + sizeofFatAndRootDir;
   811 
   828 
   812     // Check in rare case that corrupt in critical area
   829     // Check in rare case that corrupt in critical area
   813     // which includes bootsector, FAT table, (and root dir if not FAT32)
   830     // which includes bootsector, FAT table, (and root dir if not FAT32)
   814     TInt i, r;
   831     TInt i, r;
   815     for (i=0; i<iBadSectors.Count(); ++i)
   832     for (i=0; i<iBadSectors.Count(); ++i)
   816         {
   833         {
   817         TInt badSector = iBadSectors[i];
   834         const TUint badSector = iBadSectors[i];
   818         // Check in rare case that corrupt in critical area
   835         // Check in rare case that corrupt in critical area
   819         // which includes bootsector, FAT table, (and root dir if not FAT32)
   836         // which includes bootsector, FAT table, (and root dir if not FAT32)
   820         if (firstFreeSector > badSector)
   837         if (firstFreeSector > badSector)
   821             {
   838             {
   822             if (badSector == 0) // Boot sector corrupt
   839             if (badSector == 0) // Boot sector corrupt