Exemple #1
0
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);
        }
	}
/**
    Write aligned members of TFatBootSector to media
 
    @param  aMediaPos   media position the data will be written to
    @param  aBootSector data to write
    @return Media write error code
*/
TInt CFatMountCB::DoWriteBootSector(TInt64 aMediaPos, const TFatBootSector& aBootSector)  const
    {
    __PRINT2(_L("#- CFatMountCB::DoWriteBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   

    ASSERT(aMediaPos>=0);

    TBuf8<KDefaultSectorSize> bootSecBuf(KDefaultSectorSize);
    bootSecBuf.FillZ();

    //-- externalize boot sector to the data buffer
    aBootSector.Externalize(bootSecBuf);

    //-- put a boot sector signature to the last 2 bytes
    bootSecBuf[KDefaultSectorSize-2] = 0x55;
    bootSecBuf[KDefaultSectorSize-1] = 0xaa;

    //-- write boot sector to the media
    TInt r=LocalDrive()->Write(aMediaPos, bootSecBuf);
    if (r!=KErrNone)
        {//-- write failure
        __PRINT2(_L("CFatMountCB::DoWriteBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);
        }

    return r;
    }
/**
    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;
    }
/**
    Read non aligned boot data from media into TFatBootSector structure

    @param  aMediaPos   media position the data will be read from
    @param  aBootSector refrence to TFatBootSector populate
    @return Media read error code
*/
TInt CFatMountCB::DoReadBootSector(TInt64 aMediaPos, TFatBootSector& aBootSector)  const
    {
    __PRINT2(_L("#- CFatMountCB::DoReadBootSector() drv:%d, pos:0x%x"),Drive().DriveNumber(), (TUint32)aMediaPos);   

    ASSERT(aMediaPos>=0);

    TBuf8<KSizeOfFatBootSector> bootSecBuf(KSizeOfFatBootSector);
    
    //-- read boot sector from the media
    TInt r=LocalDrive()->Read(aMediaPos, KSizeOfFatBootSector, bootSecBuf);
    
    if (r != KErrNone)
        {
        __PRINT2(_L("CFatMountCB::DoReadBootSector() failed! drv:%d, code:%d"),Drive().DriveNumber(),r);

	    //-- fiddling with the error code; taken from MountL()
        if (r==KErrNotSupported)
		    return KErrNotReady;
    #if defined(_LOCKABLE_MEDIA)
	    else if(r==KErrLocked)
		    return KErrLocked;
    #endif
	    else if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
                return KErrCorrupt; 

        return r;
        }

    ASSERT(r==KErrNone);

    //-- initialise TFatBootSector object
    aBootSector.Internalize(bootSecBuf);

    //-- Validate the partition size, and fix up if the out of bounds
    TLocalDriveCapsV2Buf localDriveCaps;
    r = LocalDrive()->Caps(localDriveCaps);
    if (r != KErrNone)
        {
        //-- fiddling with the error code; taken from MountL()
        if (r!=KErrNoMemory && r!=KErrNotReady && r!=KErrCorrupt && r!=KErrUnknown)
            return KErrCorrupt;
        else
            return r;
        }

    if(!(localDriveCaps().iMediaAtt & KMediaAttVariableSize))
        {//-- this is not a RAM drive.
        const TUint32 maxSectors = I64LOW(localDriveCaps().iSize >> KDefSectorSzLog2);

        if(aBootSector.TotalSectors())
            aBootSector.SetTotalSectors(Min(aBootSector.TotalSectors(), maxSectors));
        else
            aBootSector.SetHugeSectors(Min(aBootSector.HugeSectors(), maxSectors));
        }

    return KErrNone;
    }
/**
Create the boot sector on media for the volume. For FAT32 also creates a backup copy of the boot sector.

@leave System wide error codes
*/
void CFatFormatCB::CreateBootSectorL()
	{
	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());

    _LIT8(KName_Fat12,"FAT12   ");    ///< Name in BPB given to a Fat12 volume
    _LIT8(KName_Fat16,"FAT16   ");    ///< Name in BPB given to a Fat16 volume
    _LIT8(KName_Fat32,"FAT32   ");    ///< Name in BPB given to a Fat32 volume
    _LIT8(KDefaultVendorID, "EPOC");  ///< Vendor Name for BPB for any volume formated using a Symbian OS device

    const TBool bFat32 = Is32BitFat();
    
    TFatBootSector bootSector;

	bootSector.SetVendorID(KDefaultVendorID);
	bootSector.SetBytesPerSector(iBytesPerSector);
	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
	bootSector.SetReservedSectors(iReservedSectors);
	bootSector.SetNumberOfFats(iNumberOfFats);
	iCountOfClusters=iMaxDiskSectors/iSectorsPerCluster;
	if (!bFat32)
		{
		if (iCountOfClusters>(TInt)KMaxTUint16)
			User::Leave(KErrTooBig);
		}

	bootSector.SetReservedByte(0);
	TTime timeID;
	timeID.HomeTime();
	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate Volume UniqueID from time
	bootSector.SetVolumeLabel(_L8(""));
	
    //-- set a text string in BPB that corresponds to the FS type
    switch(FatType())
        {
        case EFat12:
            bootSector.SetFileSysType(KName_Fat12);
        break;
        
        case EFat16:
            bootSector.SetFileSysType(KName_Fat16);
        break;
        
        case EFat32:
            bootSector.SetFileSysType(KName_Fat32);
        break;

        default:
            ASSERT(0);
            User::Leave(KErrArgument);
        };



	bootSector.SetJumpInstruction();
	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
	bootSector.SetNumberOfHeads(iNumberOfHeads);
	bootSector.SetHiddenSectors(iHiddenSectors);
	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
	bootSector.SetPhysicalDriveNumber(128);
	bootSector.SetExtendedBootSignature(0x29);

	if(bFat32)
		{
		bootSector.SetFatSectors(0);
		bootSector.SetFatSectors32(iSectorsPerFat);
		bootSector.SetRootDirEntries(0);
		bootSector.SetTotalSectors(0);
		bootSector.SetHugeSectors(iMaxDiskSectors);
		bootSector.SetFATFlags(0);			
		bootSector.SetVersionNumber(0x00);	
		bootSector.SetRootClusterNum(iRootClusterNum);
		bootSector.SetFSInfoSectorNum(KFSInfoSectorNum);	
        bootSector.SetBkBootRecSector(KBkBootSectorNum);
		}
	else//fat12 and 16
		{
		bootSector.SetFatSectors32(0);
		bootSector.SetFatSectors(iSectorsPerFat);
		bootSector.SetRootDirEntries(iRootDirEntries);

		if (iMaxDiskSectors<=KMaxTUint16)
			{
			bootSector.SetTotalSectors(iMaxDiskSectors);
			bootSector.SetHugeSectors(0);
			}
		else
			{
			bootSector.SetTotalSectors(0);
			bootSector.SetHugeSectors(iMaxDiskSectors);
			}
		}

	//-- write main boot sector to the first sector on media
    User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
	
    //-- for FAT32 write backup copy of the boot sector
    if(bFat32)
        {
        User::LeaveIfError(FatMount().DoWriteBootSector(KBkBootSectorNum*bootSector.BytesPerSector(), bootSector));    
        }

    }
/**
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());
	}