utilityapps/filebrowser/fileopserver/src/FBDrivePartitioner.cpp
changeset 55 2d9cac8919d3
parent 0 d6fe6244b863
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilityapps/filebrowser/fileopserver/src/FBDrivePartitioner.cpp	Mon Oct 18 16:30:05 2010 +0300
@@ -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;
+    }
+
+// --------------------------------------------------------------------------------------------