/** Read and validate the boot sector. If there is an error in reading the main boot sector (sec:0) or it is invalid, tries to read backup boot sector from sec:6. Flag iMainBootSecValid indicates the validity of the main boot sector. if it is false, but ret. value is KErrNone, it means that the backup boot sector was used and it is valid. @param aBootSector reference to the boot sector object to be read. @param aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector @return standard error code. */ TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool aDoNotReadBkBootSec/*=EFalse*/) { iMainBootSecValid = EFalse; //-- read main boot sector from the sector 0 TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector); if(nRes == KErrNone) { if(aBootSector.IsValid()) { iMainBootSecValid = ETrue; //-- main boot sector is valid, everything is OK return KErrNone; } else { __PRINT(_L("MainBoot Sector is invalid! dump:\n")); aBootSector.PrintDebugInfo(); nRes = KErrCorrupt; } } ASSERT(nRes!= KErrNone && !iMainBootSecValid); if(aDoNotReadBkBootSec) return nRes; //-- main boot sector is invalid, try backup one (it might not present at all) __PRINT(_L("Using backup boot sector...\n")); nRes=DoReadBootSector(KBkBootSectorNum << KDefSectorSzLog2, aBootSector); if(nRes == KErrNone ) { if(aBootSector.IsValid()) return KErrNone; //-- main boot sector is bad, but backup one is OK else {//-- backup boot sector is invalid __PRINT(_L("Backup Sector is invalid! dump:\n")); aBootSector.PrintDebugInfo(); nRes = KErrCorrupt; } } //-- can't read boot sectors, or both are invalid return nRes; }
void ReadBootSector(TFatBootSector& aBootSector) { TInt r = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<<KDefaultSectorLog2, aBootSector); test_KErrNone(r); if(!aBootSector.IsValid()) { test.Printf(_L("Wrong bootsector! Dump:\n")); aBootSector.PrintDebugInfo(); test(0); } }
/** Mount a Fat volume. @param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs @leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown. */ void CFatMountCB::MountL(TBool aForceMount) { const TInt driveNo = Drive().DriveNumber(); __PRINT3(_L("CFatMountCB::MountL() drv:%d, forceMount=%d, RuggedFAT:%d\n"), driveNo, aForceMount, IsRuggedFSys()); ASSERT(State() == ENotMounted || State() == EDismounted); SetState(EMounting); SetReadOnly(EFalse); User::LeaveIfError(CreateDrive(driveNo)); //-- read FAT configuration parameters from estart.txt iFatConfig.ReadConfig(driveNo); //-- initialise interface to the low-level drive access if(!iDriverInterface.Init(this)) User::LeaveIfError(KErrNoMemory); //-- get drive capabilities TLocalDriveCapsV2Buf capsBuf; User::LeaveIfError(LocalDrive()->Caps(capsBuf)); iSize=capsBuf().iSize; iRamDrive = EFalse; if(capsBuf().iMediaAtt & KMediaAttVariableSize) {//-- this is a RAM drive UserSvr::UnlockRamDrive(); iRamDrive = ETrue; } if(aForceMount) {//-- the state is "forcedly mounted", special case. This is an inconsistent state. SetState(EInit_Forced); return; } //-- read boot sector. If main is damaged, try to use backup one instead if this is not a RAM drive. TFatBootSector bootSector; User::LeaveIfError(ReadBootSector(bootSector, iRamDrive)); //-- print out boot sector debug information bootSector.PrintDebugInfo(); //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt SetFatType(bootSector.FatType()); ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector() if(bootSector.RootDirEntries() == 0 && !Is32BitFat()) {//-- FAT types mismatch. BPB_RootEntCnt is 0, which can be only for FAT32, but the number of clusters is less //-- than required for FAT32. Probably this is incorrectly FAT32 formatted media. Put the drive into ReadOnly mode, assuming //-- that is FAT32. __PRINT(_L("FAT type mismatch! Setting drive to ReadOnly mode for FAT32. \n")); SetFatType(EFat32); //-- force FAT type to be FAT32 SetReadOnly(ETrue); } //-- store volume UID, it can be checked on Remount iUniqueID = bootSector.UniqueID(); //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid() iVolParam.Populate(bootSector); //-- initialize the volume InitializeL(capsBuf()); ASSERT(State()==EInit_R); GetVolumeLabelFromDiskL(bootSector); __PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State()); }