filebrowser/fileopserver/src/FBDrivePartitioner.cpp
changeset 0 d6fe6244b863
equal deleted inserted replaced
-1:000000000000 0:d6fe6244b863
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32test.h>
       
    20 #include <e32std.h>
       
    21 #include <f32fsys.h>
       
    22 #include <e32property.h>
       
    23 
       
    24 #include "FBDrivePartitioner.h"
       
    25 
       
    26 
       
    27 // copied from coreapplicationuisdomainpskeys.h
       
    28 const TUid KPSUidCoreApplicationUIs = { 0x101F8767 };
       
    29 const TUint32 KCoreAppUIsMmcRemovedWithoutEject = 0x00000109;
       
    30 enum TCoreAppUIsMmcRemovedWithoutEject
       
    31     {
       
    32     ECoreAppUIsEjectCommandUsedUninitialized = 0,
       
    33     ECoreAppUIsEjectCommandNotUsed,
       
    34     ECoreAppUIsEjectCommandUsed,
       
    35     ECoreAppUIsEjectCommandUsedToDrive // Low 16-bits contain this value and high 16-bits TDriveNumber to eject
       
    36     };
       
    37 
       
    38 
       
    39 // trace macros
       
    40 #define TRACE(a) {_LIT( KMsg, a ); RDebug::Print(KMsg);}
       
    41 #define TRACE1(a,b) {_LIT( KMsg, a ); RDebug::Print(KMsg,b);}
       
    42 #define TRACE2(a,b,c) {_LIT( KMsg, a ); RDebug::Print(KMsg,b,c);}
       
    43 
       
    44 	
       
    45 // Set the partition alignment boundary
       
    46 const TInt KPartitionAlignment = 0x1000; // 4kB
       
    47 const TInt KMBRSize = 512;
       
    48 const TInt KSectorSize = 512;
       
    49 const TInt KMBRPartitionInfoOffset = 0x1BE;
       
    50 const TInt KLargeFAT16Partition = 0x2000000; // 32MB
       
    51 const TInt KPartitionEntrySize = 16;
       
    52 
       
    53 // Set for the iX86BootIndicator
       
    54 //const TInt KPartitionBootable = 0x80;
       
    55 const TInt KPartitionNonBootable = 0x0;
       
    56 
       
    57 
       
    58 class TMBRPartition
       
    59 	{
       
    60 public:
       
    61 	TUint8 iX86BootIndicator;
       
    62 	TUint8 iStartHead;
       
    63 	TUint8 iStartSector;
       
    64 	TUint8 iStartCylinder;
       
    65 	TUint8 iPartitionType;
       
    66 	TUint8 iEndHead;
       
    67 	TUint8 iEndSector;
       
    68 	TUint8 iEndCylinder;
       
    69 	TUint32 iFirstSector;
       
    70 	TUint32 iNumSectors;
       
    71 	};
       
    72 
       
    73 
       
    74 // --------------------------------------------------------------------------------------------
       
    75 
       
    76 TInt FBDrivePartioner::FindLocalDriveNumber(RFs& aFs, TInt aDriveNumber, TInt& aLocalDriveNum)
       
    77     {
       
    78     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: start aDriveNumber=%d", aDriveNumber );
       
    79 
       
    80     TInt err(KErrNone);
       
    81     
       
    82     TDriveInfo driveInfo;
       
    83     err = aFs.Drive(driveInfo, aDriveNumber);
       
    84 
       
    85     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get DriveInfo err=%d", err );
       
    86 
       
    87 
       
    88     TVolumeInfo vi;
       
    89     err = aFs.Volume(vi, aDriveNumber);
       
    90 
       
    91     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get VolumeInfo err=%d", err );
       
    92 
       
    93 
       
    94     TMediaSerialNumber serialNum;
       
    95     err = aFs.GetMediaSerialNumber(serialNum, aDriveNumber);
       
    96 
       
    97     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: get MediaSerialNumber err=%d", err );
       
    98 
       
    99 
       
   100     TInt len = serialNum.Length();
       
   101     TInt n(0);
       
   102     for (n=0; n<len; n+=16)
       
   103         {
       
   104         TBuf16<16*3 +1> buf;
       
   105         for (TInt m=n; m<n+16; m++)
       
   106             {
       
   107             TBuf16<3> hexBuf;
       
   108             hexBuf.Format(_L("%02X "),serialNum[m]);
       
   109             buf.Append(hexBuf);
       
   110             }
       
   111         buf.Append(_L("\n"));
       
   112         }
       
   113 
       
   114     TBusLocalDrive drv;
       
   115     TBool chg(EFalse);
       
   116     aLocalDriveNum = -1;
       
   117     for (n=0; n<KMaxLocalDrives; n++)
       
   118         {
       
   119         TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Connect drive %d", n );
       
   120         err = drv.Connect(n, chg); //for user area
       
   121         TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Connect returns %d", err );
       
   122 
       
   123         if(err != KErrNone)
       
   124             {
       
   125             continue;
       
   126             }    
       
   127 
       
   128         TLocalDriveCapsV5Buf capsBuf;
       
   129         TLocalDriveCapsV5& caps = capsBuf();
       
   130         err = drv.Caps(capsBuf);
       
   131         TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: drv.Caps returns %d", err );
       
   132 
       
   133         if(err != KErrNone)
       
   134             {
       
   135             continue;
       
   136             }    
       
   137 
       
   138         TPtrC8 localSerialNum(caps.iSerialNum, caps.iSerialNumLength);
       
   139         if (serialNum.Compare(localSerialNum) == 0)
       
   140             {
       
   141             TBool sizeMatch = (vi.iSize < caps.iSize)?ETrue:EFalse;
       
   142             if (sizeMatch)
       
   143                 {
       
   144                 aLocalDriveNum = n;
       
   145                 TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: sizeMatch for localDrive %d", n );
       
   146                 }
       
   147             else
       
   148                 {
       
   149                 TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: sizeMatch failed for localDrive %d", n );
       
   150                 }
       
   151 
       
   152             }
       
   153 
       
   154         drv.Disconnect();
       
   155         }
       
   156 
       
   157     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: localDriveNum=%d", aLocalDriveNum );
       
   158 
       
   159     err = aLocalDriveNum == -1 ? KErrNotFound : KErrNone;
       
   160     
       
   161     TRACE1( "FBDrivePartitioner::FindLocalDriveNumber: returns %d", err );
       
   162     return err;    
       
   163 
       
   164     }
       
   165 	
       
   166 // --------------------------------------------------------------------------------------------
       
   167 
       
   168 TInt FBDrivePartioner::EraseMBR(RFs& aFs, TInt aDriveNumber)
       
   169 	{
       
   170     TRACE1( "FBDrivePartitioner::EraseMBR: start aDriveNumber=%d", aDriveNumber );
       
   171 
       
   172     // Prevent SysAp shutting down applications
       
   173     RProperty::Set(
       
   174         KPSUidCoreApplicationUIs,
       
   175         KCoreAppUIsMmcRemovedWithoutEject,
       
   176         ECoreAppUIsEjectCommandUsed );
       
   177 
       
   178 	TInt err(KErrNone);
       
   179 
       
   180 	TInt localDriveNumber;
       
   181 	err = FindLocalDriveNumber(aFs, aDriveNumber, localDriveNumber);
       
   182 	
       
   183 	if (err != KErrNone)
       
   184 	    {
       
   185     	TRACE1("FBDrivePartitioner::EraseMBR: FindLocalDriveNumber err=%d returning", err); 
       
   186 	    return err;
       
   187 	    }
       
   188 	
       
   189 	TRACE1("FBDrivePartitioner::EraseMBR: connecting to local drive %d", localDriveNumber); 
       
   190 
       
   191 	TBusLocalDrive drv;
       
   192 	TBool chg(EFalse);
       
   193 	err = drv.Connect(localDriveNumber, chg); //for user area
       
   194 
       
   195 	TRACE1("FBDrivePartitioner::EraseMBR: drv.Connect %d", err);
       
   196 
       
   197 	
       
   198 	TRACE("FBDrivePartitioner::EraseMBR: Now start to invalidate MBR"); 
       
   199 
       
   200 	// create a buffers of zeros
       
   201 	TBuf8<KMBRSize> mbrBuf;
       
   202 	mbrBuf.Fill(0, mbrBuf.MaxLength());
       
   203 
       
   204 /*	
       
   205 	// write the next 16 sectors with the buffer. Usually you only write the first one, but this one should erase any following invalid sectors
       
   206 	for (TInt i=0; i<16; i++)
       
   207 	    {
       
   208     	err = drv.Write(i*KMBRSize, KMBRSize, &mbrBuf, -1 , 0, 0x40000000);  // RLocalDrive::ELocDrvWholeMedia==0x40000000
       
   209        	TRACE2("FBDrivePartitioner::EraseMBR: sector %d, write returns %d", i+1, err); 
       
   210 	    }
       
   211 */
       
   212 
       
   213     // erase the MBR
       
   214 	err = drv.Write(0, KMBRSize, &mbrBuf, -1 , 0, 0x40000000);  // RLocalDrive::ELocDrvWholeMedia==0x40000000
       
   215    	TRACE1("FBDrivePartitioner::EraseMBR: write returns %d", err); 
       
   216 
       
   217 	drv.Disconnect();
       
   218 
       
   219 	// force a remount, if this is the protected area, then it will have to be remounted
       
   220     TRACE1( "FBDrivePartitioner::EraseMBR: Remounting drive number %d", aDriveNumber );
       
   221 	TInt err2 = aFs.RemountDrive(aDriveNumber, NULL, 0);
       
   222     TRACE1( "FBDrivePartitioner::EraseMBR: RemountDrive err2=%d", err2 );
       
   223 
       
   224     TRACE1( "FBDrivePartitioner::EraseMBR: returns %d", err );
       
   225     return err;
       
   226     }
       
   227 
       
   228 // --------------------------------------------------------------------------------------------
       
   229 
       
   230 TInt FBDrivePartioner::CreatePartitions(RFs& aFs, TInt aDriveNumber, TInt aPartCount)
       
   231 	{
       
   232     TRACE2( "FBDrivePartitioner::CreatePartitions: start aDriveNumber=%d aPartCount=%d", aDriveNumber, aPartCount );
       
   233 	TInt err(KErrNone);
       
   234 
       
   235     TUint8 MBRPartitionInfo[ KPartitionEntrySize*KMBRMaxPrimaryPartitions ];
       
   236 
       
   237     // Prevent SysAp shutting down applications
       
   238     RProperty::Set(
       
   239         KPSUidCoreApplicationUIs,
       
   240         KCoreAppUIsMmcRemovedWithoutEject,
       
   241         ECoreAppUIsEjectCommandUsed );
       
   242 
       
   243 	// Force the system to read the memory card erased MBR
       
   244 	err = aFs.RemountDrive( aDriveNumber );
       
   245 	TRACE1( "FBDrivePartitioner::CreatePartitions: Remount result %d", err );
       
   246 	
       
   247 	// Get the number of partitions from user
       
   248     TUint8 partitionCount(aPartCount);
       
   249 	TBool change = EFalse;
       
   250 	TInt mcDriveNbr(2);
       
   251 	TLocalDriveCapsV4 dc;
       
   252 	TInt64 diskSpace(0);
       
   253 
       
   254 /*
       
   255 	err = FindLocalDriveNumber(aFs, aDriveNumber, mcDriveNbr);
       
   256 	
       
   257 	if (err != KErrNone)
       
   258 	    {
       
   259     	TRACE1("FBDrivePartitioner::CreatePartitions: FindLocalDriveNumber err=%d returning", err); 
       
   260 	    return err;
       
   261 	    }
       
   262 */
       
   263 
       
   264 	// Seek through the system drives to find memory card drive
       
   265 	for (TInt i = 0; i < KMaxLocalDrives; ++i)
       
   266 		{
       
   267 		RLocalDrive	d;
       
   268 		change = EFalse;
       
   269 		err = d.Connect(i, change);
       
   270 		if (err == KErrNone)
       
   271 			{
       
   272 			TPckg<TLocalDriveCapsV4> capsPack(dc);
       
   273 			
       
   274 			if (d.Caps(capsPack) == KErrNone)
       
   275 				{
       
   276 				if (dc.iType == EMediaHardDisk)
       
   277 					{
       
   278 					mcDriveNbr = i;
       
   279 					diskSpace  = dc.iSize;
       
   280                  	TRACE1( "FBDrivePartitioner::CreatePartitions: found hard drive %d:", mcDriveNbr );
       
   281 					}
       
   282 				}
       
   283 			d.Close();
       
   284 			}
       
   285 		}
       
   286 
       
   287 	// Connect to the local drive we found
       
   288 	RLocalDrive	localDrive;
       
   289 	change = EFalse;
       
   290     err = localDrive.Connect( mcDriveNbr, change );
       
   291  	TRACE2( "FBDrivePartitioner::CreatePartitions: localDrive.Connect %d: %d", mcDriveNbr, err );
       
   292 	TRACE1( "FBDrivePartitioner::CreatePartitions: diskSpace in sectors 0x%x, %d", diskSpace / KSectorSize );
       
   293 
       
   294 	// Let's read the MBR by using RLocalDrive
       
   295 	TUint8 data[KMBRSize];
       
   296 	TPtr8 buf( &data[0], KMBRSize );
       
   297 	err = localDrive.Read( 0, KMBRSize, buf );
       
   298 	TRACE1( "FBDrivePartitioner::CreatePartitions: localDrive.Read %d", err );
       
   299 	// Let's check the current drive layout here
       
   300 	memcpy( MBRPartitionInfo, &data[KMBRPartitionInfoOffset],(sizeof(TMBRPartition)<<2)); 
       
   301 	TMBRPartition *partitionInfo = (TMBRPartition*) MBRPartitionInfo;
       
   302 
       
   303 	// Clean the rest of the MBR buffer
       
   304 	buf.FillZ();
       
   305 
       
   306 	// Print out the partition info
       
   307 	for( TInt i = 0; i<KMBRMaxPrimaryPartitions; i++ )
       
   308 		{
       
   309 		TRACE1( "FBDrivePartitioner::CreatePartitions: Partition %d", i+1 );
       
   310 		TRACE1( "FBDrivePartitioner::CreatePartitions: iX86BootIndicator %x", partitionInfo[i].iX86BootIndicator );
       
   311 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartHead        %x", partitionInfo[i].iStartHead );
       
   312 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartSector      %x", partitionInfo[i].iStartSector );
       
   313 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartCylinder    %x", partitionInfo[i].iStartCylinder );
       
   314 		TRACE1( "FBDrivePartitioner::CreatePartitions: iPartitionType    %x", partitionInfo[i].iPartitionType );
       
   315 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndHead          %x", partitionInfo[i].iEndHead );
       
   316 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndSector        %x", partitionInfo[i].iEndSector );
       
   317 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndCylinder      %x", partitionInfo[i].iEndCylinder );
       
   318 		TRACE1( "FBDrivePartitioner::CreatePartitions: iFirstSector      %x", partitionInfo[i].iFirstSector );
       
   319 		TRACE1( "FBDrivePartitioner::CreatePartitions: iNumSectors       %x", partitionInfo[i].iNumSectors );
       
   320 		}
       
   321 
       
   322 	// Calculate partition size	
       
   323 	TRACE( "FBDrivePartitioner::CreatePartitions: Calculating partition size" );
       
   324 	TInt64 partitionSize = (diskSpace / partitionCount) - KPartitionAlignment;
       
   325 	//TRACE1( "FBDrivePartitioner::CreatePartitions: PartitionSize in sectors 0x%x", partitionSize/KSectorSize );
       
   326 	TRACE1( "FBDrivePartitioner::CreatePartitions: Size of the partition is %Ld bytes", partitionSize );
       
   327 
       
   328 	// Activate the specified amount of partitions 
       
   329 	for( TInt i = 0; i < KMBRMaxPrimaryPartitions; i++ )
       
   330 		{
       
   331 		if( i < partitionCount )
       
   332 			{
       
   333 			if( partitionSize <= KLargeFAT16Partition )
       
   334 				{
       
   335 				partitionInfo[i].iPartitionType = KPartitionTypeFAT16small;
       
   336 				}
       
   337 			else
       
   338 				{
       
   339 				partitionInfo[i].iPartitionType = KPartitionTypeFAT16;
       
   340 				}
       
   341 			partitionInfo[i].iX86BootIndicator = KPartitionNonBootable;
       
   342 			}
       
   343 		else
       
   344 			{
       
   345 			partitionInfo[i].iX86BootIndicator = 0;
       
   346 			partitionInfo[i].iPartitionType = 0;
       
   347 			}
       
   348 		}
       
   349 
       
   350 	TRACE( "FBDrivePartitioner::CreatePartitions: Set first partition start address and change to sector addresses" );
       
   351 
       
   352 	// Set first partition start address
       
   353 	TInt64 offSet = KPartitionAlignment;
       
   354 	// Change to sector addresses
       
   355 	offSet = offSet / KSectorSize;
       
   356 
       
   357 	// Align and set the partitions
       
   358 	for( TInt i = 0; i < KMBRMaxPrimaryPartitions; i++ )
       
   359 		{
       
   360 		if( i < partitionCount )
       
   361 			{
       
   362 			// Start sector
       
   363 			partitionInfo[i].iFirstSector = offSet;
       
   364 			// Number of sectors in a partition
       
   365 			partitionInfo[i].iNumSectors = partitionSize / KSectorSize;
       
   366 			// Start of the next partition
       
   367 			offSet += ((partitionSize &~ (KPartitionAlignment - 1)) / KSectorSize);
       
   368 			}
       
   369 		else
       
   370 			{
       
   371 			partitionInfo[i].iFirstSector = 0;
       
   372 			partitionInfo[i].iNumSectors = 0;
       
   373 			}
       
   374 		// Start address HDD
       
   375 		partitionInfo[i].iStartHead = 0;
       
   376 		partitionInfo[i].iStartSector = 0;
       
   377 		partitionInfo[i].iStartCylinder = 0;
       
   378 		// End address HDD
       
   379 		partitionInfo[i].iEndHead = 0;
       
   380 		partitionInfo[i].iEndSector = 0;
       
   381 		partitionInfo[i].iEndCylinder = 0;
       
   382 
       
   383 		}
       
   384 
       
   385 	// Print out the new partition boot record
       
   386  	TRACE( "FBDrivePartitioner::CreatePartitions: Partitions created" );
       
   387 	for( TInt i = 0; i<KMBRMaxPrimaryPartitions; i++ )
       
   388 		{
       
   389 		TRACE1("FBDrivePartitioner::CreatePartitions: Partition %d", i+1 );
       
   390 		TRACE1( "FBDrivePartitioner::CreatePartitions: iX86BootIndicator %x", partitionInfo[i].iX86BootIndicator );
       
   391 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartHead        %x", partitionInfo[i].iStartHead );
       
   392 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartSector      %x", partitionInfo[i].iStartSector );
       
   393 		TRACE1( "FBDrivePartitioner::CreatePartitions: iStartCylinder    %x", partitionInfo[i].iStartCylinder );
       
   394 		TRACE1( "FBDrivePartitioner::CreatePartitions: iPartitionType    %x", partitionInfo[i].iPartitionType );
       
   395 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndHead          %x", partitionInfo[i].iEndHead );
       
   396 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndSector        %x", partitionInfo[i].iEndSector );
       
   397 		TRACE1( "FBDrivePartitioner::CreatePartitions: iEndCylinder      %x", partitionInfo[i].iEndCylinder );
       
   398 		TRACE1( "FBDrivePartitioner::CreatePartitions: iFirstSector      %x", partitionInfo[i].iFirstSector );
       
   399 		TRACE1( "FBDrivePartitioner::CreatePartitions: iNumSectors       %x", partitionInfo[i].iNumSectors );
       
   400 		}
       
   401 
       
   402 	// Copy the new layout to MBR buffer
       
   403  	TRACE( "FBDrivePartitioner::CreatePartitions: Copy the new layout to MBR buffer" );
       
   404 	memcpy( &data[KMBRPartitionInfoOffset], MBRPartitionInfo, (sizeof(TMBRPartition)<<2) ); 
       
   405 
       
   406 	// Make sure we have a valid signature
       
   407  	TRACE( "FBDrivePartitioner::CreatePartitions: Make sure we have a valid signature" );
       
   408 	*(TUint16*)(&data[KMBRSignatureOffset]) = 0xAA55;
       
   409 
       
   410 	// Now flush the new partition layout
       
   411  	TRACE( "FBDrivePartitioner::CreatePartitions: Flush the new partition layout" );
       
   412 	err = localDrive.Write( 0, buf );
       
   413 	TRACE1( "FBDrivePartitioner::CreatePartitions: localDrive.Write err=%d", err );
       
   414 	localDrive.Close();
       
   415 
       
   416     TRACE1( "FBDrivePartitioner::CreatePartitions: returns %d", err );
       
   417     
       
   418     return err;
       
   419     }
       
   420 
       
   421 // --------------------------------------------------------------------------------------------
       
   422 
       
   423 TInt FBDrivePartioner::FormatPartitions(RFs& aFs, TInt aDriveNumber, TInt aPartCount)
       
   424 	{
       
   425     TRACE2( "FBDrivePartitioner::FormatPartitions: aDriveNumber=%d aPartCount=%d", aDriveNumber, aPartCount );
       
   426     TInt err(KErrNone);
       
   427 
       
   428     for( TInt i = 0; i < aPartCount; i++ )
       
   429         {
       
   430         TDriveName name(TDriveUnit(aDriveNumber + i).Name());
       
   431         TRACE1( "FBDrivePartitioner::FormatPartitions: Format %S start", &name );
       
   432         RFormat fmt;
       
   433         TInt count(0);
       
   434         err = fmt.Open(aFs, name, EQuickFormat, count);
       
   435         TRACE1( "FBDrivePartitioner::FormatPartitions: Format open=%d", err );
       
   436         while (count > 0)
       
   437             {
       
   438             err = fmt.Next(count);
       
   439             if (err != KErrNone)
       
   440                 {
       
   441                 TRACE1( "FBDrivePartitioner::FormatPartitions: Format error=%d", err );
       
   442                 break;
       
   443                 }
       
   444             }
       
   445         fmt.Close();
       
   446         TRACE1( "FBDrivePartitioner::FormatPartitions: Format %S end", &name );
       
   447 	    }
       
   448 
       
   449     TRACE1("FBDrivePartitioner::FormatPartitions returns %d", err);
       
   450     
       
   451     return err;
       
   452     }
       
   453 
       
   454 // --------------------------------------------------------------------------------------------