--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/filebrowser/fileopserver/src/FBDrivePartitioner.cpp Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,454 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <e32test.h>
+#include <e32std.h>
+#include <f32fsys.h>
+#include <e32property.h>
+
+#include "FBDrivePartitioner.h"
+
+
+// copied from coreapplicationuisdomainpskeys.h
+const TUid KPSUidCoreApplicationUIs = { 0x101F8767 };
+const TUint32 KCoreAppUIsMmcRemovedWithoutEject = 0x00000109;
+enum TCoreAppUIsMmcRemovedWithoutEject
+ {
+ ECoreAppUIsEjectCommandUsedUninitialized = 0,
+ ECoreAppUIsEjectCommandNotUsed,
+ ECoreAppUIsEjectCommandUsed,
+ ECoreAppUIsEjectCommandUsedToDrive // Low 16-bits contain this value and high 16-bits TDriveNumber to eject
+ };
+
+
+// trace macros
+#define TRACE(a) {_LIT( KMsg, a ); RDebug::Print(KMsg);}
+#define TRACE1(a,b) {_LIT( KMsg, a ); RDebug::Print(KMsg,b);}
+#define TRACE2(a,b,c) {_LIT( KMsg, a ); RDebug::Print(KMsg,b,c);}
+
+
+// Set the partition alignment boundary
+const TInt KPartitionAlignment = 0x1000; // 4kB
+const TInt KMBRSize = 512;
+const TInt KSectorSize = 512;
+const TInt KMBRPartitionInfoOffset = 0x1BE;
+const TInt KLargeFAT16Partition = 0x2000000; // 32MB
+const TInt KPartitionEntrySize = 16;
+
+// Set for the iX86BootIndicator
+//const TInt KPartitionBootable = 0x80;
+const TInt KPartitionNonBootable = 0x0;
+
+
+class TMBRPartition
+ {
+public:
+ TUint8 iX86BootIndicator;
+ TUint8 iStartHead;
+ TUint8 iStartSector;
+ TUint8 iStartCylinder;
+ TUint8 iPartitionType;
+ TUint8 iEndHead;
+ TUint8 iEndSector;
+ TUint8 iEndCylinder;
+ TUint32 iFirstSector;
+ TUint32 iNumSectors;
+ };
+
+
+// --------------------------------------------------------------------------------------------
+
+TInt FBDrivePartioner::FindLocalDriveNumber(RFs& aFs, TInt aDriveNumber, TInt& aLocalDriveNum)
+ {
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: start aDriveNumber=%d", aDriveNumber );
+
+ TInt err(KErrNone);
+
+ TDriveInfo driveInfo;
+ err = aFs.Drive(driveInfo, aDriveNumber);
+
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get DriveInfo err=%d", err );
+
+
+ TVolumeInfo vi;
+ err = aFs.Volume(vi, aDriveNumber);
+
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get VolumeInfo err=%d", err );
+
+
+ TMediaSerialNumber serialNum;
+ err = aFs.GetMediaSerialNumber(serialNum, aDriveNumber);
+
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get MediaSerialNumber err=%d", err );
+
+
+ TInt len = serialNum.Length();
+ TInt n(0);
+ for (n=0; n<len; n+=16)
+ {
+ TBuf16<16*3 +1> buf;
+ for (TInt m=n; m<n+16; m++)
+ {
+ TBuf16<3> hexBuf;
+ hexBuf.Format(_L("%02X "),serialNum[m]);
+ buf.Append(hexBuf);
+ }
+ buf.Append(_L("\n"));
+ }
+
+ TBusLocalDrive drv;
+ TBool chg(EFalse);
+ aLocalDriveNum = -1;
+ for (n=0; n<KMaxLocalDrives; n++)
+ {
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Connect drive %d", n );
+ err = drv.Connect(n, chg); //for user area
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Connect returns %d", err );
+
+ if(err != KErrNone)
+ {
+ continue;
+ }
+
+ TLocalDriveCapsV5Buf capsBuf;
+ TLocalDriveCapsV5& caps = capsBuf();
+ err = drv.Caps(capsBuf);
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Caps returns %d", err );
+
+ if(err != KErrNone)
+ {
+ continue;
+ }
+
+ TPtrC8 localSerialNum(caps.iSerialNum, caps.iSerialNumLength);
+ if (serialNum.Compare(localSerialNum) == 0)
+ {
+ TBool sizeMatch = (vi.iSize < caps.iSize)?ETrue:EFalse;
+ if (sizeMatch)
+ {
+ aLocalDriveNum = n;
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: sizeMatch for localDrive %d", n );
+ }
+ else
+ {
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: sizeMatch failed for localDrive %d", n );
+ }
+
+ }
+
+ drv.Disconnect();
+ }
+
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: localDriveNum=%d", aLocalDriveNum );
+
+ err = aLocalDriveNum == -1 ? KErrNotFound : KErrNone;
+
+ TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: returns %d", err );
+ return err;
+
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt FBDrivePartioner::EraseMBR(RFs& aFs, TInt aDriveNumber)
+ {
+ TRACE1( "FBDrivePartitioner::EraseMBR: start aDriveNumber=%d", aDriveNumber );
+
+ // Prevent SysAp shutting down applications
+ RProperty::Set(
+ KPSUidCoreApplicationUIs,
+ KCoreAppUIsMmcRemovedWithoutEject,
+ ECoreAppUIsEjectCommandUsed );
+
+ TInt err(KErrNone);
+
+ TInt localDriveNumber;
+ err = FindLocalDriveNumber(aFs, aDriveNumber, localDriveNumber);
+
+ if (err != KErrNone)
+ {
+ TRACE1("FBDrivePartitioner::EraseMBR: FindLocalDriveNumber err=%d returning", err);
+ return err;
+ }
+
+ TRACE1("FBDrivePartitioner::EraseMBR: connecting to local drive %d", localDriveNumber);
+
+ TBusLocalDrive drv;
+ TBool chg(EFalse);
+ err = drv.Connect(localDriveNumber, chg); //for user area
+
+ TRACE1("FBDrivePartitioner::EraseMBR: drv.Connect %d", err);
+
+
+ TRACE("FBDrivePartitioner::EraseMBR: Now start to invalidate MBR");
+
+ // create a buffers of zeros
+ TBuf8<KMBRSize> mbrBuf;
+ mbrBuf.Fill(0, mbrBuf.MaxLength());
+
+/*
+ // write the next 16 sectors with the buffer. Usually you only write the first one, but this one should erase any following invalid sectors
+ for (TInt i=0; i<16; i++)
+ {
+ err = drv.Write(i*KMBRSize, KMBRSize, &mbrBuf, -1 , 0, 0x40000000); // RLocalDrive::ELocDrvWholeMedia==0x40000000
+ TRACE2("FBDrivePartitioner::EraseMBR: sector %d, write returns %d", i+1, err);
+ }
+*/
+
+ // erase the MBR
+ err = drv.Write(0, KMBRSize, &mbrBuf, -1 , 0, 0x40000000); // RLocalDrive::ELocDrvWholeMedia==0x40000000
+ TRACE1("FBDrivePartitioner::EraseMBR: write returns %d", err);
+
+ drv.Disconnect();
+
+ // force a remount, if this is the protected area, then it will have to be remounted
+ TRACE1( "FBDrivePartitioner::EraseMBR: Remounting drive number %d", aDriveNumber );
+ TInt err2 = aFs.RemountDrive(aDriveNumber, NULL, 0);
+ TRACE1( "FBDrivePartitioner::EraseMBR: RemountDrive err2=%d", err2 );
+
+ TRACE1( "FBDrivePartitioner::EraseMBR: returns %d", err );
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt FBDrivePartioner::CreatePartitions(RFs& aFs, TInt aDriveNumber, TInt aPartCount)
+ {
+ TRACE2( "FBDrivePartitioner::CreatePartitions: start aDriveNumber=%d aPartCount=%d", aDriveNumber, aPartCount );
+ TInt err(KErrNone);
+
+ TUint8 MBRPartitionInfo[ KPartitionEntrySize*KMBRMaxPrimaryPartitions ];
+
+ // Prevent SysAp shutting down applications
+ RProperty::Set(
+ KPSUidCoreApplicationUIs,
+ KCoreAppUIsMmcRemovedWithoutEject,
+ ECoreAppUIsEjectCommandUsed );
+
+ // Force the system to read the memory card erased MBR
+ err = aFs.RemountDrive( aDriveNumber );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: Remount result %d", err );
+
+ // Get the number of partitions from user
+ TUint8 partitionCount(aPartCount);
+ TBool change = EFalse;
+ TInt mcDriveNbr(2);
+ TLocalDriveCapsV4 dc;
+ TInt64 diskSpace(0);
+
+/*
+ err = FindLocalDriveNumber(aFs, aDriveNumber, mcDriveNbr);
+
+ if (err != KErrNone)
+ {
+ TRACE1("FBDrivePartitioner::CreatePartitions: FindLocalDriveNumber err=%d returning", err);
+ return err;
+ }
+*/
+
+ // Seek through the system drives to find memory card drive
+ for (TInt i = 0; i < KMaxLocalDrives; ++i)
+ {
+ RLocalDrive d;
+ change = EFalse;
+ err = d.Connect(i, change);
+ if (err == KErrNone)
+ {
+ TPckg<TLocalDriveCapsV4> capsPack(dc);
+
+ if (d.Caps(capsPack) == KErrNone)
+ {
+ if (dc.iType == EMediaHardDisk)
+ {
+ mcDriveNbr = i;
+ diskSpace = dc.iSize;
+ TRACE1( "FBDrivePartitioner::CreatePartitions: found hard drive %d:", mcDriveNbr );
+ }
+ }
+ d.Close();
+ }
+ }
+
+ // Connect to the local drive we found
+ RLocalDrive localDrive;
+ change = EFalse;
+ err = localDrive.Connect( mcDriveNbr, change );
+ TRACE2( "FBDrivePartitioner::CreatePartitions: localDrive.Connect %d: %d", mcDriveNbr, err );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: diskSpace in sectors 0x%x, %d", diskSpace / KSectorSize );
+
+ // Let's read the MBR by using RLocalDrive
+ TUint8 data[KMBRSize];
+ TPtr8 buf( &data[0], KMBRSize );
+ err = localDrive.Read( 0, KMBRSize, buf );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: localDrive.Read %d", err );
+ // Let's check the current drive layout here
+ memcpy( MBRPartitionInfo, &data[KMBRPartitionInfoOffset],(sizeof(TMBRPartition)<<2));
+ TMBRPartition *partitionInfo = (TMBRPartition*) MBRPartitionInfo;
+
+ // Clean the rest of the MBR buffer
+ buf.FillZ();
+
+ // Print out the partition info
+ for( TInt i = 0; i<KMBRMaxPrimaryPartitions; i++ )
+ {
+ TRACE1( "FBDrivePartitioner::CreatePartitions: Partition %d", i+1 );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iX86BootIndicator %x", partitionInfo[i].iX86BootIndicator );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartHead %x", partitionInfo[i].iStartHead );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartSector %x", partitionInfo[i].iStartSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartCylinder %x", partitionInfo[i].iStartCylinder );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iPartitionType %x", partitionInfo[i].iPartitionType );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndHead %x", partitionInfo[i].iEndHead );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndSector %x", partitionInfo[i].iEndSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndCylinder %x", partitionInfo[i].iEndCylinder );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iFirstSector %x", partitionInfo[i].iFirstSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iNumSectors %x", partitionInfo[i].iNumSectors );
+ }
+
+ // Calculate partition size
+ TRACE( "FBDrivePartitioner::CreatePartitions: Calculating partition size" );
+ TInt64 partitionSize = (diskSpace / partitionCount) - KPartitionAlignment;
+ //TRACE1( "FBDrivePartitioner::CreatePartitions: PartitionSize in sectors 0x%x", partitionSize/KSectorSize );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: Size of the partition is %Ld bytes", partitionSize );
+
+ // Activate the specified amount of partitions
+ for( TInt i = 0; i < KMBRMaxPrimaryPartitions; i++ )
+ {
+ if( i < partitionCount )
+ {
+ if( partitionSize <= KLargeFAT16Partition )
+ {
+ partitionInfo[i].iPartitionType = KPartitionTypeFAT16small;
+ }
+ else
+ {
+ partitionInfo[i].iPartitionType = KPartitionTypeFAT16;
+ }
+ partitionInfo[i].iX86BootIndicator = KPartitionNonBootable;
+ }
+ else
+ {
+ partitionInfo[i].iX86BootIndicator = 0;
+ partitionInfo[i].iPartitionType = 0;
+ }
+ }
+
+ TRACE( "FBDrivePartitioner::CreatePartitions: Set first partition start address and change to sector addresses" );
+
+ // Set first partition start address
+ TInt64 offSet = KPartitionAlignment;
+ // Change to sector addresses
+ offSet = offSet / KSectorSize;
+
+ // Align and set the partitions
+ for( TInt i = 0; i < KMBRMaxPrimaryPartitions; i++ )
+ {
+ if( i < partitionCount )
+ {
+ // Start sector
+ partitionInfo[i].iFirstSector = offSet;
+ // Number of sectors in a partition
+ partitionInfo[i].iNumSectors = partitionSize / KSectorSize;
+ // Start of the next partition
+ offSet += ((partitionSize &~ (KPartitionAlignment - 1)) / KSectorSize);
+ }
+ else
+ {
+ partitionInfo[i].iFirstSector = 0;
+ partitionInfo[i].iNumSectors = 0;
+ }
+ // Start address HDD
+ partitionInfo[i].iStartHead = 0;
+ partitionInfo[i].iStartSector = 0;
+ partitionInfo[i].iStartCylinder = 0;
+ // End address HDD
+ partitionInfo[i].iEndHead = 0;
+ partitionInfo[i].iEndSector = 0;
+ partitionInfo[i].iEndCylinder = 0;
+
+ }
+
+ // Print out the new partition boot record
+ TRACE( "FBDrivePartitioner::CreatePartitions: Partitions created" );
+ for( TInt i = 0; i<KMBRMaxPrimaryPartitions; i++ )
+ {
+ TRACE1("FBDrivePartitioner::CreatePartitions: Partition %d", i+1 );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iX86BootIndicator %x", partitionInfo[i].iX86BootIndicator );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartHead %x", partitionInfo[i].iStartHead );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartSector %x", partitionInfo[i].iStartSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iStartCylinder %x", partitionInfo[i].iStartCylinder );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iPartitionType %x", partitionInfo[i].iPartitionType );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndHead %x", partitionInfo[i].iEndHead );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndSector %x", partitionInfo[i].iEndSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iEndCylinder %x", partitionInfo[i].iEndCylinder );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iFirstSector %x", partitionInfo[i].iFirstSector );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: iNumSectors %x", partitionInfo[i].iNumSectors );
+ }
+
+ // Copy the new layout to MBR buffer
+ TRACE( "FBDrivePartitioner::CreatePartitions: Copy the new layout to MBR buffer" );
+ memcpy( &data[KMBRPartitionInfoOffset], MBRPartitionInfo, (sizeof(TMBRPartition)<<2) );
+
+ // Make sure we have a valid signature
+ TRACE( "FBDrivePartitioner::CreatePartitions: Make sure we have a valid signature" );
+ *(TUint16*)(&data[KMBRSignatureOffset]) = 0xAA55;
+
+ // Now flush the new partition layout
+ TRACE( "FBDrivePartitioner::CreatePartitions: Flush the new partition layout" );
+ err = localDrive.Write( 0, buf );
+ TRACE1( "FBDrivePartitioner::CreatePartitions: localDrive.Write err=%d", err );
+ localDrive.Close();
+
+ TRACE1( "FBDrivePartitioner::CreatePartitions: returns %d", err );
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------
+
+TInt FBDrivePartioner::FormatPartitions(RFs& aFs, TInt aDriveNumber, TInt aPartCount)
+ {
+ TRACE2( "FBDrivePartitioner::FormatPartitions: aDriveNumber=%d aPartCount=%d", aDriveNumber, aPartCount );
+ TInt err(KErrNone);
+
+ for( TInt i = 0; i < aPartCount; i++ )
+ {
+ TDriveName name(TDriveUnit(aDriveNumber + i).Name());
+ TRACE1( "FBDrivePartitioner::FormatPartitions: Format %S start", &name );
+ RFormat fmt;
+ TInt count(0);
+ err = fmt.Open(aFs, name, EQuickFormat, count);
+ TRACE1( "FBDrivePartitioner::FormatPartitions: Format open=%d", err );
+ while (count > 0)
+ {
+ err = fmt.Next(count);
+ if (err != KErrNone)
+ {
+ TRACE1( "FBDrivePartitioner::FormatPartitions: Format error=%d", err );
+ break;
+ }
+ }
+ fmt.Close();
+ TRACE1( "FBDrivePartitioner::FormatPartitions: Format %S end", &name );
+ }
+
+ TRACE1("FBDrivePartitioner::FormatPartitions returns %d", err);
+
+ return err;
+ }
+
+// --------------------------------------------------------------------------------------------