os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_fmt.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\sfat\sl_fmt.cpp
    15 // 
    16 //
    17 
    18 #include "sl_std.h"
    19 #include <e32hal.h>
    20 
    21 
    22 
    23 
    24 //
    25 // Returns the total available ram from UserHal:: or sets an
    26 // arbitrary limit upon the WINS ramdisk.
    27 //
    28 static TInt64 GetRamDiskSizeInBytes()
    29 	{
    30 
    31 #if defined(__EPOC32__)
    32 	TMemoryInfoV1Buf memInfo;
    33 	UserHal::MemoryInfo(memInfo);
    34 	TUint max = memInfo().iTotalRamInBytes; // not really the correct max
    35 	return max;
    36 #else
    37     const TInt KArbitraryWinsRamDiskSize=0x400000;  //-- Default size for a Ram drive, 4MB
    38 	return(KArbitraryWinsRamDiskSize);
    39 #endif
    40 	}
    41 
    42 CFatFormatCB::CFatFormatCB()
    43 	{
    44 	__PRINT1(_L("CFatFormatCB::CFatFormatCB() [%x]"),this);
    45     }
    46 
    47 CFatFormatCB::~CFatFormatCB()
    48 	{
    49 	__PRINT1(_L("CFatFormatCB::~CFatFormatCB() [%x]"),this);
    50     iBadSectors.Close();
    51 	iBadClusters.Close();
    52 	}
    53 
    54 TInt CFatFormatCB::MaxFat16Sectors() const
    55 //
    56 // Calculate the size of a 16 bit FAT
    57 //
    58 	{
    59 	
    60 	TInt fatSizeInBytes=(2*iMaxDiskSectors)/iSectorsPerCluster+(iBytesPerSector-1);
    61 	return(fatSizeInBytes/iBytesPerSector);
    62 	}
    63 
    64 TInt CFatFormatCB::MaxFat12Sectors() const
    65 //
    66 // Calculate the size of a 12 bit FAT
    67 //
    68 	{
    69 	
    70 	TInt maxDiskClusters=iMaxDiskSectors/iSectorsPerCluster;
    71 	TInt fatSizeInBytes=maxDiskClusters+(maxDiskClusters>>1)+(iBytesPerSector-1);
    72 	return(fatSizeInBytes/iBytesPerSector);
    73 	}
    74 
    75 //-------------------------------------------------------------------------------------------------------------------
    76 /**
    77     Fill a media range from aStartPos to aEndPos with zeroes.
    78     @param  aStartPos   start media position
    79     @param  aEndPos     end media position
    80 */
    81 void CFatFormatCB::DoZeroFillMediaL(TInt64 aStartPos, TInt64 aEndPos)
    82     {
    83     ASSERT(aStartPos <= aEndPos && aStartPos >=0  && aEndPos >=0);
    84 
    85     RBuf8 buf;
    86     CleanupClosePushL(buf);
    87 
    88     const TInt KBufMaxSz=32768; //-- zero-buffer Maximal size, bytes
    89     const TInt KBufMinSz=512;   //-- zero-buffer minimal size, bytes
    90 
    91     if(buf.CreateMax(KBufMaxSz) != KErrNone)
    92         {
    93         buf.CreateMaxL(KBufMinSz); //-- OOM, try to create smaller buffer
    94         }
    95 
    96     buf.FillZ();
    97 
    98     TInt64 rem = aEndPos - aStartPos;
    99     while(rem)
   100         {
   101         const TUint32 bytesToWrite=(TUint32)Min(rem, buf.Size());
   102         TPtrC8 ptrData(buf.Ptr(), bytesToWrite);
   103 
   104         User::LeaveIfError(LocalDrive()->Write(aStartPos, ptrData));
   105 
   106         aStartPos+=bytesToWrite;
   107         rem-=bytesToWrite;
   108         }
   109     
   110     CleanupStack::PopAndDestroy(&buf); 
   111     }
   112 
   113 //-------------------------------------------------------------------------------------------------------------------
   114 
   115 static TInt DiskSizeInSectorsL(TInt64 aSizeInBytes)
   116 	{
   117     const TInt64 totalSectors64=aSizeInBytes>>KDefSectorSzLog2;
   118 	const TInt   totalSectors32=I64LOW(totalSectors64);
   119     __PRINT2(_L("Disk size:%LU, max disk sectors:%d"),aSizeInBytes, totalSectors32);
   120     return totalSectors32;
   121 	}
   122 
   123 
   124 /**
   125     suggest FAT type according to the FAT volume metrics
   126     @return calculated FAT type
   127 */
   128 TFatType CFatFormatCB::SuggestFatType() const
   129 {
   130     const TUint32 rootDirSectors = (iRootDirEntries*KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector;
   131     const TUint32 dataSectors = iMaxDiskSectors - (iReservedSectors + (iNumberOfFats * iSectorsPerFat) + rootDirSectors);
   132     const TUint32 clusterCnt = dataSectors/ iSectorsPerCluster;
   133 
   134     //-- magic. see FAT specs for details.
   135     if(clusterCnt < 4085)
   136         return EFat12;
   137     else if(clusterCnt < 65525)
   138         return EFat16;
   139     else
   140         return EFat32;
   141 }
   142 
   143 /**
   144     Initialize format data.
   145 */
   146 void CFatFormatCB::InitializeFormatDataL()
   147 	{
   148       
   149 	__PRINT1(_L("CFatFormatCB::InitializeFormatDataL() drv:%d"), Drive().DriveNumber());
   150 	TLocalDriveCapsV6Buf caps;
   151 	User::LeaveIfError(LocalDrive()->Caps(caps));
   152 	iVariableSize=((caps().iMediaAtt)&KMediaAttVariableSize) ? (TBool)ETrue : (TBool)EFalse;
   153 
   154 	iBytesPerSector=KDefaultSectorSize;
   155 	iSectorSizeLog2 = Log2(iBytesPerSector);
   156 	iHiddenSectors=caps().iHiddenSectors;	
   157 	iNumberOfHeads=2;
   158 	iSectorsPerTrack=16;
   159 	
   160     if (iVariableSize)
   161 		{// Variable size implies ram disk
   162 		iMaxDiskSectors=DiskSizeInSectorsL(GetRamDiskSizeInBytes());
   163 		InitFormatDataForVariableSizeDisk(iMaxDiskSectors);
   164 		}
   165 	else
   166 		{//-- fixed-size media
   167         iMaxDiskSectors=DiskSizeInSectorsL(caps().iSize);
   168 		
   169         __PRINT3(_L("::InitializeFormatDataL() iMode:0x%x, ilen:%d, extrai:%d"), iMode, iSpecialInfo.Length(), caps().iExtraInfo);
   170 
   171         if(iMode & ESpecialFormat)
   172 		    {
   173 		    if(iSpecialInfo.Length())
   174 			    {
   175                 if (caps().iExtraInfo)  // conflict between user and media
   176                     User::Leave(KErrNotSupported);
   177 			    else  // User-specified
   178                     User::LeaveIfError(InitFormatDataForFixedSizeDiskUser(iMaxDiskSectors));
   179                 }
   180     		else
   181     		    {
   182                 if (caps().iExtraInfo)
   183                     User::LeaveIfError(InitFormatDataForFixedSizeDiskCustom(caps().iFormatInfo));
   184                 else
   185     			    User::LeaveIfError(InitFormatDataForFixedSizeDiskNormal(iMaxDiskSectors, caps()));
   186                 }
   187 		    }
   188         else //if(iMode & ESpecialFormat)
   189             {
   190             // Normal format with default values
   191             //  - Media with special format requirements will always use them
   192             //    even without the ESpecialFormat option.
   193             if(caps().iExtraInfo)
   194 	            User::LeaveIfError(InitFormatDataForFixedSizeDiskCustom(caps().iFormatInfo));
   195             else
   196 	            User::LeaveIfError(InitFormatDataForFixedSizeDiskNormal(iMaxDiskSectors, caps()));
   197 		    }
   198         
   199         } //else(iVariableSize)
   200 	}
   201 
   202 /**
   203     Initialize the format parameters for a variable sized disk
   204     
   205     @param  aDiskSizeInSectors volume size in sectors
   206     @return standard error code
   207 */
   208 TInt  CFatFormatCB::InitFormatDataForVariableSizeDisk(TInt aDiskSizeInSectors)
   209 	{
   210 	iNumberOfFats=2; // 1 FAT 1 Indirection table (FIT)
   211 	iReservedSectors=1;
   212 	iRootDirEntries=2*(4*KDefaultSectorSize)/sizeof(SFatDirEntry);
   213 	TInt minSectorsPerCluster=(aDiskSizeInSectors+KMaxFAT16Entries-1)/KMaxFAT16Entries;
   214 	iSectorsPerCluster=1;
   215 	while (minSectorsPerCluster>iSectorsPerCluster)
   216 		iSectorsPerCluster<<=1;
   217 	__PRINT1(_L("iSectorsPerCluster = %d"),iSectorsPerCluster);
   218 	iSectorsPerFat=MaxFat16Sectors();
   219 	__PRINT1(_L("iSectorsPerFat = %d"),iSectorsPerFat);
   220 	iFileSystemName=KFileSystemName16;
   221 
   222 	return KErrNone;
   223 	}
   224 
   225 TInt CFatFormatCB::HandleCorrupt(TInt aError)
   226 //
   227 // Handle disk corrupt during format. It needs media driver's support.
   228 // Media driver should handle DLocalDrive::EGetLastErrorInfo request in
   229 // its Request function, filling in proper error information.
   230 // @see TErrorInfo
   231 //
   232     {
   233 	__PRINT2(_L("CFatFormatCB::HandleCorrupt(%d) drv:%d"), aError, Drive().DriveNumber());
   234 
   235     TPckgBuf<TErrorInfo> info;
   236 	TInt r = LocalDrive()->GetLastErrorInfo(info);
   237     
   238     if(r != KErrNone)
   239         {
   240         __PRINT1(_L("....GetLastErrorInfo() err:%d"), r);
   241         }
   242 
   243     if (r == KErrNotSupported)
   244 		return KErrCorrupt;
   245     else if (r != KErrNone)
   246         return r;
   247 
   248     __PRINT3(_L("....TErrorInfo iReasonCode:%d, iErrorPos:%LU, iOtherInfo:%d"), info().iReasonCode, info().iErrorPos, info().iOtherInfo);
   249 	
   250     // if no error reported by GetLastErrorInfo(), return the original error
   251 	if (info().iReasonCode == KErrNone)
   252 		return aError;
   253 
   254     if (info().iReasonCode!=KErrNone && info().iReasonCode!=TErrorInfo::EBadSector)
   255         return info().iReasonCode;
   256 
   257     // First bad sector met
   258     TInt sectorsDone = (TInt)(info().iErrorPos >> iSectorSizeLog2);
   259     TInt badSector = iFormatInfo.i512ByteSectorsFormatted + sectorsDone;
   260     iBadSectors.Append(badSector);
   261 
   262     // Update format information
   263     iFormatInfo.i512ByteSectorsFormatted += sectorsDone+1;
   264     return KErrNone;
   265     }
   266 
   267 void CFatFormatCB::TranslateL()
   268 //
   269 // Change bad cluster number to new value with regard to new format parameters
   270 //
   271     {
   272     if (iDiskCorrupt || !(iMode & EQuickFormat))
   273         return;
   274 
   275     TInt size = 1 << FatMount().ClusterSizeLog2();
   276     TUint8* readBuf = new(ELeave) TUint8[size];
   277     TPtr8 readBufPtr(readBuf, size);
   278     RArray<TInt> newArray;
   279     TInt r = DoTranslate(readBufPtr, newArray);
   280     delete[] readBuf;
   281     newArray.Close();
   282     User::LeaveIfError(r);
   283     }
   284 
   285 #define calcSector(n) (n+oFirstFreeSector-nFirstFreeSector)
   286 TInt CFatFormatCB::DoTranslate(TPtr8& aBuf, RArray<TInt>& aArray)
   287     {
   288 
   289     TInt r = KErrNone;
   290 
   291     // old format parameters
   292     TInt oFirstFreeSector = iOldFirstFreeSector;
   293     TInt oSectorsPerCluster = iOldSectorsPerCluster;
   294     // new format parameters
   295     TInt nFirstFreeSector = FatMount().iFirstFreeByte>>FatMount().SectorSizeLog2();
   296     TInt nSectorsPerCluster = FatMount().SectorsPerCluster();
   297 
   298     if (oFirstFreeSector==nFirstFreeSector && oSectorsPerCluster==nSectorsPerCluster)
   299         return r;
   300 
   301     TInt i;
   302     for (i=0; i<iBadClusters.Count(); ++i)
   303         {
   304         /*
   305         Cluster boundary may change due to format parameter change.
   306         Old: |-- ... --|----|----|----|----|----|----|----|
   307                        |<-          Data area           ->|
   308         New: |--- ... ---|------|------|------|------|------|
   309                          |<-           Data area          ->|
   310         */
   311         TInt begSector = calcSector((iBadClusters[i]-2)*oSectorsPerCluster);
   312         begSector = Max(begSector, nFirstFreeSector);
   313         TInt endSector = calcSector(((iBadClusters[i]-1)*oSectorsPerCluster)-1);
   314         endSector = Max(endSector, nFirstFreeSector);
   315         TInt begCluster = (begSector/iSectorsPerCluster)+KFatFirstSearchCluster;
   316         TInt endCluster = (endSector/iSectorsPerCluster)+KFatFirstSearchCluster;
   317         if (begCluster == endCluster)  // old cluster is in a new cluster
   318             {
   319             if (aArray.Find(begCluster) == KErrNotFound)
   320                 if ((r=aArray.Append(begCluster)) != KErrNone)
   321                     return r;
   322             continue;
   323             }
   324         // deal with old cluster cross over several new clusters
   325         TInt offset = (begSector-(begCluster-2)*iSectorsPerCluster)<<iSectorSizeLog2;
   326         TInt len = (endSector-(endCluster-2)*iSectorsPerCluster)<<iSectorSizeLog2;
   327         TInt j;
   328         for (j=begCluster; j<=endCluster; ++j)
   329         // Because each old bad cluster cross several new clusters,
   330         // we have to verify which new cluster is bad really
   331             {
   332             TInt addr = (nFirstFreeSector+(j-2)*iSectorsPerCluster)<<iSectorSizeLog2;
   333             TInt clusterLen = (1<<iSectorSizeLog2) * iSectorsPerCluster;
   334             if (j == begCluster)
   335                 r = LocalDrive()->Read(addr+offset,clusterLen-offset,aBuf);
   336             else if (j == endCluster && len)
   337                 r = LocalDrive()->Read(addr,len,aBuf);
   338             else
   339                 r = LocalDrive()->Read(addr,clusterLen,aBuf);
   340             if (r == KErrCorrupt) // new cluster j is corrupt
   341                 if ((r=aArray.Append(j)) != KErrNone)
   342                     return r;
   343             }
   344         }
   345     // Update iBadClusters with aArray
   346     iBadClusters.Reset();
   347     for (i=0; i<aArray.Count(); ++i)
   348         if ((r=iBadClusters.Append(aArray[i])) != KErrNone)
   349             return r;
   350     iBadClusters.Sort();
   351     return r;
   352     }
   353 
   354 
   355 //-------------------------------------------------------------------------------------------------------------------
   356 /** override from CFormatCB, additional interfaces implementation */
   357 TInt CFatFormatCB::GetInterface(TInt aInterfaceId, TAny*& /*aInterface*/, TAny* aInput)
   358     {
   359     if(aInterfaceId == ESetFmtParameters)
   360         {
   361         return DoProcessTVolFormatParam((const TVolFormatParam_FAT*)aInput);
   362         }
   363 
   364     return KErrNotSupported;
   365     }
   366 
   367 //-------------------------------------------------------------------------------------------------------------------
   368 /** 
   369     Process formatting parameters passed as TVolFormatParam_FAT structure.
   370     @param      apVolFormatParam pointer to the formatting parameters.
   371     @return     standard error code
   372 */
   373 TInt CFatFormatCB::DoProcessTVolFormatParam(const TVolFormatParam_FAT* apVolFormatParam)
   374     {
   375     if(apVolFormatParam->iUId != TVolFormatParam::KUId ||  apVolFormatParam->FSNameHash() != TVolFormatParam::CalcFSNameHash(KFileSystemName_FAT))
   376         {
   377         ASSERT(0);
   378         return KErrArgument;
   379         }
   380 
   381     //-- Populate iSpecialInfo with the data taken from apVolFormatParam.
   382     //-- for formatting FAT volume iSpecialInfo can hold absolutely all required data from apVolFormatParam.
   383     //-- if some additional data from apVolFormatParam are required for some reason, figure out youself how to store and use them.
   384     TLDFormatInfo& fmtInfo = iSpecialInfo();
   385     new(&fmtInfo) TLDFormatInfo; //-- initialise the structure in the buffer 
   386 
   387 
   388     //-- sectors per cluster
   389     fmtInfo.iSectorsPerCluster = (TUint16)apVolFormatParam->SectPerCluster();   
   390     
   391     //-- FAT type
   392     const TFatSubType fatSubType = apVolFormatParam->FatSubType();
   393     
   394     if(fatSubType != ENotSpecified && fatSubType != EFat12 && fatSubType != EFat16 && fatSubType != EFat32)
   395         return KErrArgument;
   396 
   397 
   398     fmtInfo.iFATBits = (TLDFormatInfo::TFATBits)fatSubType; //-- FAT12/16/32/not specified
   399 
   400     //-- number of FAT tables
   401     switch(apVolFormatParam->NumFATs())
   402         {
   403         case 0: //-- "not specified, default"
   404         break;
   405 
   406         case 1:
   407             fmtInfo.iFlags |= TLDFormatInfo::EOneFatTable; 
   408         break;
   409 
   410         case 2:
   411             fmtInfo.iFlags |= TLDFormatInfo::ETwoFatTables; 
   412         break;
   413 
   414         default: //-- more than KMaxFatTablesSupported is not supported
   415         return KErrArgument;
   416 
   417         };
   418 
   419     //-- number of reserved sectors
   420     fmtInfo.iReservedSectors = (TUint16)apVolFormatParam->ReservedSectors();
   421 
   422     return KErrNone;
   423     }
   424 
   425 
   426 
   427 
   428 
   429 
   430 
   431 
   432 
   433 
   434