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