kerneltest/e32test/mediaext/d_nfe.cpp
changeset 109 b3a1d9898418
child 152 657f875b013e
equal deleted inserted replaced
102:ef2a444a7410 109:b3a1d9898418
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\mediext\d_nfe.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <drivers/locmedia.h>
       
    19 #include <platform.h>
       
    20 #include <variantmediadef.h>
       
    21 #include "nfe.h"
       
    22 
       
    23 #if defined(_DEBUG)
       
    24 	#define TRACE_ENABLED
       
    25 #else
       
    26 #endif
       
    27 
       
    28 #if defined(TRACE_ENABLED)
       
    29 #define __KTRACE_PRINT(p) {p;}
       
    30 #else
       
    31 #define __KTRACE_PRINT(p)
       
    32 #endif
       
    33 
       
    34 
       
    35 
       
    36 
       
    37 // Variant parameters for test Media Extension Driver
       
    38 
       
    39 
       
    40 const TInt KNfeThreadPriority = 24;	        // same as file server
       
    41 const TInt KNfeDiskOpReady = 100;       //100%
       
    42 //const TInt KNfeDiskOpStart = 0;         //0%
       
    43 
       
    44 _LIT(KPddName, "Media.NFE");
       
    45 #define NFE_DRIVENAME "NFE"
       
    46 #define NFE_NUMMEDIA 1
       
    47 
       
    48 // Define the array of local drives which we're attaching to
       
    49 __ASSERT_COMPILE(sizeof(TNfeDeviceInfo) <= 256);	// KMaxQueryDeviceLength
       
    50 
       
    51 // Define the array of local code-paging drives which we're attaching to
       
    52 #ifdef __DEMAND_PAGING__
       
    53 	__ASSERT_COMPILE(NFE_PAGEDRIVECOUNT <= TNfeDeviceInfo::ENfeMaxPartitionEntries);
       
    54 	__ASSERT_COMPILE(NFE_DRIVECOUNT >= NFE_PAGEDRIVECOUNT);
       
    55 	#define	SECTOR_SHIFT 9
       
    56 #endif	// #ifdef __DEMAND_PAGING__
       
    57 
       
    58 
       
    59 
       
    60 
       
    61 class DPrimaryMediaExt : public DPrimaryMediaBase
       
    62 	{
       
    63 public:
       
    64 	DPrimaryMediaExt(TInt aInstance);
       
    65 public:
       
    66 	TInt iInstance;
       
    67 	TDfcQue iNfeDfcQ;
       
    68 	};
       
    69 
       
    70 
       
    71 
       
    72 // Get the number of drives in the drive array belonging to this instance 
       
    73 TInt DriveCount(TInt aInstance)
       
    74 	{
       
    75 	static const TInt NfeInstanceDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_DRIVE_COUNTS};
       
    76 	return NfeInstanceDriveCounts[aInstance];
       
    77 	}
       
    78 
       
    79 // Get a pointer to the first drive in the drive array belonging to this instance 
       
    80 const TInt* DriveList(TInt aInstance)
       
    81 	{
       
    82 	static const TInt NfeDriveNumbers[NFE_DRIVECOUNT]={NFE_DRIVELIST};
       
    83 	TInt driveListOffset = 0;
       
    84 	for (TInt n=0; n<aInstance; n++)
       
    85 		driveListOffset+= DriveCount(n);
       
    86 	return  NfeDriveNumbers + driveListOffset;
       
    87 	}
       
    88 
       
    89 const TInt* DriveLetterList(TInt aInstance)
       
    90 	{
       
    91 	static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
       
    92 	TInt driveListOffset = 0;
       
    93 	for (TInt n=0; n<aInstance; n++)
       
    94 		driveListOffset+= DriveCount(n);
       
    95 	return  NfeDriveLetters + driveListOffset;
       
    96 	}
       
    97 
       
    98 TInt DriveLetter(TInt aIndex)
       
    99 	{
       
   100 	static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
       
   101 	return NfeDriveLetters[aIndex];
       
   102 	}
       
   103 
       
   104 TChar DriveLetterToAscii(TInt aDriveLetter)
       
   105 	{
       
   106 	return aDriveLetter >= 0 && aDriveLetter <= 25 ? aDriveLetter +'A' : '?';
       
   107 	}
       
   108 
       
   109 #ifdef __DEMAND_PAGING__
       
   110 	// Get the number of drives in the paged drive array belonging to this instance 
       
   111 	TInt PageDriveCount(TInt aInstance)
       
   112 		{
       
   113 	#if NFE_PAGEDRIVECOUNT > 0
       
   114 		static const TInt NfeInstancePageDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGEDRIVE_COUNTS};
       
   115 		return NfeInstancePageDriveCounts[aInstance];
       
   116 	#else
       
   117 		return 0;
       
   118 	#endif
       
   119 		}
       
   120 
       
   121 	// Get a pointer to the first drive in the paged drive array belonging to this instance 
       
   122 	const TInt* PageDriveList(TInt aInstance)
       
   123 		{
       
   124 	#if NFE_PAGEDRIVECOUNT > 0
       
   125 		static const TInt NfePageDriveNumbers[NFE_PAGEDRIVECOUNT]={NFE_PAGEDRIVELIST};
       
   126 		TInt driveListOffset = 0;
       
   127 		for (TInt n=0; n<aInstance; n++)
       
   128 			driveListOffset+= PageDriveCount(n);
       
   129 		return  NfePageDriveNumbers + driveListOffset;
       
   130 	#else
       
   131 		return NULL;
       
   132 	#endif
       
   133 		}
       
   134 
       
   135 	// Get the number of paging type belonging to this instance 
       
   136 	TInt PagingType(TInt aInstance)
       
   137 		{
       
   138 	#if NFE_PAGEDRIVECOUNT > 0
       
   139 		static const TInt NfeInstancePagingType[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGING_TYPE};
       
   140 		return NfeInstancePagingType[aInstance];
       
   141 	#else
       
   142 		return 0;
       
   143 	#endif
       
   144 		}
       
   145 
       
   146 	// get the instance of the swap drive
       
   147 	TInt SwapInstance()
       
   148 		{
       
   149 		for (TInt i=0; i<NFE_INSTANCE_COUNT; i++)
       
   150 			if (PagingType(i) & DPagingDevice::EData)
       
   151 				return i;
       
   152 		return KErrNotFound;
       
   153 		}
       
   154 #endif	// #ifdef __DEMAND_PAGING__
       
   155 
       
   156 
       
   157 const char* DriveStatus(TNfeDiskStatus aStatus)
       
   158 	{
       
   159 	const char* KNfeUnmounted = "Unmounted";
       
   160 	const char* KNfeDecrypted = "Decrypted";
       
   161 	const char* KNfeDecrypting = "Decrypting";
       
   162 	const char* KNfeEncrypted = "Encrypted";
       
   163 	const char* KNfeEncrypting = "Encrypting";
       
   164 	const char* KNfeWiping = "Wiping";
       
   165 	const char* KNfeCorrupted = "Corrupted";
       
   166 	const char* KNfeUnrecognised = "Unrecognised";
       
   167 
       
   168 	switch(aStatus)
       
   169 		{
       
   170 		case ENfeUnmounted:
       
   171 			return KNfeUnmounted;
       
   172 		case ENfeDecrypted:
       
   173 			return KNfeDecrypted;
       
   174 		case ENfeDecrypting:
       
   175 			return KNfeDecrypting;
       
   176 		case ENfeEncrypted:
       
   177 			return KNfeEncrypted;
       
   178 		case ENfeEncrypting:
       
   179 			return KNfeEncrypting;
       
   180 		case ENfeWiping:
       
   181 			return KNfeWiping;
       
   182 		case ENfeCorrupted:
       
   183 			return KNfeCorrupted;
       
   184 		default:
       
   185 			return KNfeUnrecognised;
       
   186 
       
   187 		}
       
   188 	}
       
   189 
       
   190 
       
   191 DPrimaryMediaExt::DPrimaryMediaExt(TInt aInstance) : iInstance(aInstance)
       
   192 	{
       
   193 	}
       
   194 
       
   195 
       
   196 #define NFE_FAULT()	Kern::Fault("NFEMEDIA",__LINE__)
       
   197 
       
   198 // disk encryption/decryption/wiping is only performed after the following period of inactivity
       
   199 // NB USB Mass Storage tends to 'poll' the media driver by sending ECaps every second or so, so we need
       
   200 // to ensure this timeout period is significantly less to ensure the timer DFC thread gets a chance to run...
       
   201 const TInt KNotBusyInterval = 200;		// 200 mS
       
   202 
       
   203 
       
   204 
       
   205 class DPhysicalDeviceMediaNFE : public DPhysicalDevice
       
   206 	{
       
   207 public:
       
   208 	DPhysicalDeviceMediaNFE();
       
   209 	virtual TInt Install();
       
   210 	virtual void GetCaps(TDes8& aDes) const;
       
   211 	virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
       
   212 	virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
       
   213 	virtual TInt Info(TInt aFunction, TAny* a1);
       
   214 	};
       
   215 								
       
   216 
       
   217 class DMediaDriverNFE : public DMediaDriverExtension
       
   218 	{
       
   219 public:
       
   220 	class TPropertyObserver
       
   221 		{
       
   222 	public:
       
   223 		void Close();
       
   224 		static void PropertySubsCompleteFn(TAny* aPtr, TInt aReason);
       
   225 	public:
       
   226 		TInt iDriveIndex;
       
   227 		DMediaDriverNFE* iMediaExt;
       
   228 		RPropertyRef iProperty;
       
   229 		TPropertySubsRequest* iPropertySubsRequest;
       
   230 		TDfc* iPropertyDfc;	// N.B. subscription call backs don't occur in our thread context, hence the need for this DFC
       
   231 		TInt iValue;
       
   232 		};
       
   233 
       
   234 public:
       
   235 	 DMediaDriverNFE(TInt aMediaId);
       
   236 	~DMediaDriverNFE();
       
   237 
       
   238 	// replacing pure virtual
       
   239 	virtual TInt Request(TLocDrvRequest& aRequest);
       
   240 	virtual TInt PartitionInfo(TPartitionInfo &anInfo);
       
   241 
       
   242 	TInt DoCreate(TInt aMediaId);
       
   243 	void Close();
       
   244 
       
   245 	TNfeDriveInfo*  GetSwapDrive();
       
   246 
       
   247 private:
       
   248 	TInt HandleRead(TLocDrvRequest& aRequest);
       
   249 	TInt HandleWrite(TLocDrvRequest& aRequest);
       
   250 	TInt HandleFormat(TLocDrvRequest& aRequest);
       
   251 	TInt HandleCaps(TLocDrvRequest& aReq);
       
   252 
       
   253 
       
   254 	void EncryptBuffer(TDes8& aBuffer);
       
   255 	void DecryptBuffer(TDes8& aBuffer);
       
   256 
       
   257 	inline TUint8 EncryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
       
   258 	inline TUint8 DecryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
       
   259 	inline TInt DriveIndex(TInt aDriveNum) {return iDriveNumToIndex[aDriveNum];}
       
   260 
       
   261 	static void IdleTimerCallBack(TAny* aMediaDriver);
       
   262 	static void TimerDfcFunction(TAny* aMediaDriver);
       
   263 
       
   264 	// Publish & Subscribe stuff - used to listen to requests from UI 
       
   265 	static void FromUiPropertyDfcFunction(TAny* aObserver);
       
   266 	void FromUiPropertyDfc(TPropertyObserver& aObserver);
       
   267 
       
   268 	// Publish & Subscribe stuff - used to listen to status setting from other NFE drives
       
   269 	static void StatusToUiPropertyDfcFunction(TAny* aObserver);
       
   270 	void StatusToUiPropertyDfc(TPropertyObserver& aObserver);
       
   271 
       
   272 	void StartEncrypting();
       
   273 	void StartDecrypting();
       
   274 
       
   275 	TInt HandleDiskContent();	// called from idle timer DFC
       
   276 
       
   277 	TNfeDriveInfo* NextDrive();
       
   278 	
       
   279 	TBool AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen);
       
   280 
       
   281 	void SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus);
       
   282 
       
   283 	TBool ValidBootSector(TUint8* aBuffer);
       
   284 	TUint32 VolumeId(TUint8* aBuffer);
       
   285 	void CheckBootSector(TNfeDriveInfo &aDriveInfo);
       
   286 	TInt WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised = EFalse);
       
   287 
       
   288 private:
       
   289 	TInt iInstance;		// media drive instance
       
   290 
       
   291 	// A local buffer use for encryting / decrypting
       
   292 	// For paging requests we need this to be page aligned, so allocate enough to cater for 
       
   293 	// the worst case of up to 4K being wasted at the start of the buffer and the end
       
   294 	enum {KSectorSize = 512, KPageSize = 4096, KBufSize = 65536};
       
   295 	TUint8 iNonPageAlignedBuffer[KBufSize + KPageSize*2];
       
   296 	// a pointer to the start of the first page in iNonPageAlignedBuffer
       
   297 	TUint8* iBuffer;
       
   298 
       
   299 	
       
   300 	// Idle timer & DFC for kicking an encryption pass
       
   301 	NTimer iIdleTimer;
       
   302 	TDfc iTimerDfc;
       
   303 
       
   304 	TInt iDriveIndex;								// index of local drive number currently being encrypted
       
   305 	TInt iDriveNumToIndex[KMaxPartitionEntries];	// maps drive numbers to index
       
   306 
       
   307 	TBool iBusy;
       
   308 
       
   309 	const TInt* iDriveList;	// pointer into the drives in NFE_DRIVELIST belonging to this media driver
       
   310 	const TInt* iDriveLetterList;	// pointer into the drive letter in NFE_DRIVELETTERLIST belonging to this media driver
       
   311 
       
   312 	// Publish & subscribe stuff which handles drive command notification events from the UI
       
   313 	TPropertyObserver iFromUiPropertyObserver[NFE_DRIVECOUNT];
       
   314 
       
   315 	// Publish & subscribe stuff which handles drive status notification events from the other NFE drives
       
   316 	TPropertyObserver iStatusToUiPropertyObserver[NFE_DRIVECOUNT];
       
   317 
       
   318 	TBool iDriveFinalised;
       
   319 
       
   320 public:
       
   321 	// Partition information etc for drives this driver is attached to
       
   322 	TNfeDeviceInfo iInfo;
       
   323 	};
       
   324 
       
   325 
       
   326 
       
   327 class TBootSectorStatus
       
   328 	{
       
   329 public:
       
   330 	TUint8 iFatBootSectorData[128];
       
   331 	
       
   332 	enum {ENfeBootSectorSignature = 0x2045464E};	// 'NFE '
       
   333 	TUint32 iSignature;
       
   334 
       
   335 	TNfeDiskStatus iStatus;
       
   336 	TBool iFinalised;
       
   337 	TInt64 iEncryptEndPos;	// position of the last encrypted byte +1. Only written when device is powered down
       
   338 	};
       
   339 
       
   340 
       
   341 DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()
       
   342 	{
       
   343 	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()"));
       
   344 	iUnitsMask=0x1;
       
   345 	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
       
   346 	}
       
   347 
       
   348 /**
       
   349 Install the Internal NFE PDD.
       
   350 */
       
   351 TInt DPhysicalDeviceMediaNFE::Install()
       
   352 	{
       
   353 	__KTRACE_PRINT(Kern::Printf(": TInt DPhysicalDeviceMediaNFE::Install()"));
       
   354 
       
   355 	return SetName(&KPddName);
       
   356 	}
       
   357 
       
   358 void DPhysicalDeviceMediaNFE::GetCaps(TDes8& /*aDes*/) const
       
   359 	{
       
   360 	}
       
   361 
       
   362 /**
       
   363 Create an NFE media driver.
       
   364 */
       
   365 TInt DPhysicalDeviceMediaNFE::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
       
   366 	{
       
   367 	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Create()"));
       
   368 
       
   369 	if (!Kern::QueryVersionSupported(iVersion,aVer))
       
   370 		return KErrNotSupported;
       
   371 
       
   372 	TInt r=KErrNoMemory;
       
   373 
       
   374 	DMediaDriverNFE* pD = new DMediaDriverNFE(aMediaId);
       
   375 	aChannel=pD;
       
   376 	if (pD)
       
   377 		r=pD->DoCreate(aMediaId);
       
   378 
       
   379 	if (r == KErrNone)
       
   380 		pD->OpenMediaDriverComplete(KErrNone);
       
   381 
       
   382 	return r;
       
   383 	}
       
   384 
       
   385 TInt DPhysicalDeviceMediaNFE::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
       
   386 	{
       
   387 	TInt r;
       
   388 	if (!Kern::QueryVersionSupported(iVersion,aVer))
       
   389 		r = KErrNotSupported;
       
   390 	else if (aDeviceType == MEDIA_DEVICE_NFE)
       
   391 		return r = KErrNone;
       
   392 	else
       
   393 		r = KErrNotSupported;
       
   394 
       
   395 //	__KTRACE_PRINT(Kern::Printf("DPhysicalDeviceMediaNFE::Validate() aDeviceType %d NfeDeviceType %d r %d", aDeviceType, MEDIA_DEVICE_NFE, r));
       
   396 	return r;
       
   397 	}
       
   398 
       
   399 TInt DPhysicalDeviceMediaNFE::Info(TInt aFunction, TAny*)
       
   400 //
       
   401 // Return the priority of this media driver
       
   402 //
       
   403 	{
       
   404 //	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Info()"));
       
   405 
       
   406 	if (aFunction==EPriority)
       
   407 		return KMediaDriverPriorityNormal;
       
   408 
       
   409 	if (aFunction==EMediaDriverPersistent)
       
   410 		return KErrNone;
       
   411 
       
   412 	return KErrNotSupported;
       
   413 	}
       
   414 
       
   415 DMediaDriverNFE::DMediaDriverNFE(TInt aMediaId) :
       
   416 	DMediaDriverExtension(aMediaId),
       
   417 	iInstance(((DPrimaryMediaExt*) iPrimaryMedia)->iInstance),
       
   418 	iIdleTimer(IdleTimerCallBack,this),
       
   419 	iTimerDfc(TimerDfcFunction,this,2),
       
   420 	iDriveList (DriveList(iInstance)),
       
   421 	iDriveLetterList (DriveLetterList(iInstance))
       
   422 	{
       
   423 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DMediaDriverNFE()", iInstance));
       
   424 	iInfo.iDriveCount = DriveCount(iInstance);
       
   425 
       
   426 	__ASSERT_ALWAYS(Kern::RoundToPageSize(1) == KPageSize, NFE_FAULT());
       
   427 
       
   428 	// Align the buffer to a page boundary to improve efficiency for paging requests
       
   429 	iBuffer = &iNonPageAlignedBuffer[0];
       
   430 	iBuffer = (TUint8*) ((((TUint32) &iNonPageAlignedBuffer[0]) + KPageSize-1) & ~(KPageSize-1));
       
   431 	}
       
   432 
       
   433 DMediaDriverNFE::~DMediaDriverNFE()
       
   434 //
       
   435 // Destructor.
       
   436 //
       
   437 	{
       
   438 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::~DMediaDriverNFE()", iInstance));
       
   439 
       
   440 	TInt i;
       
   441 	for (i=0; i<TNfeDeviceInfo::ENfeMaxPartitionEntries; i++)
       
   442 		{
       
   443 		RPropertyRef* property = (RPropertyRef*) iInfo.iDrives[i].iStatusToUiProperty;
       
   444 		if (property)
       
   445 			{
       
   446 			property->Delete();
       
   447 			delete property;
       
   448 			}
       
   449 		property = (RPropertyRef*) iInfo.iDrives[i].iToUiProperty;
       
   450 		if (property)
       
   451 			{
       
   452 			property->Delete();
       
   453 			delete property;
       
   454 			}
       
   455 		property = (RPropertyRef*) iInfo.iDrives[i].iProgressToUiProperty;
       
   456 		if (property)
       
   457 			{
       
   458 			property->Delete();
       
   459 			delete property;
       
   460 			}
       
   461 		}
       
   462 
       
   463 	for (i=0; i<NFE_DRIVECOUNT; i++)
       
   464 		{
       
   465 		iFromUiPropertyObserver[i].Close();
       
   466 		iStatusToUiPropertyObserver[i].Close();
       
   467 		}
       
   468 	}
       
   469 
       
   470 
       
   471 TInt CreateKey(RPropertyRef*& aProperty, TUint aKey)
       
   472 	{
       
   473 	aProperty = new RPropertyRef;
       
   474 	if (aProperty == NULL)
       
   475 		return KErrNoMemory;
       
   476 	TInt r = aProperty->Attach(KNfeUID, aKey);
       
   477 	if (r != KErrNone)
       
   478 		return r;
       
   479 
       
   480     static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
       
   481 	r = aProperty->Define( RProperty::EInt, KPassPolicy, KPassPolicy );
       
   482 	if (r != KErrNone && r != KErrAlreadyExists)
       
   483 		return r;
       
   484 	return KErrNone;
       
   485 	}
       
   486 
       
   487 TInt DMediaDriverNFE::DoCreate(TInt /*aMediaId*/)
       
   488 //
       
   489 // Create the media driver.
       
   490 //
       
   491 	{
       
   492 	__KTRACE_PRINT(Kern::Printf("NFE%d: TInt DMediaDriverNFE::DoCreate()", iInstance));
       
   493 
       
   494 	// Associate the idle timer DFC with our thread
       
   495 	iTimerDfc.SetDfcQ(iPrimaryMedia->iDfcQ);
       
   496 
       
   497 	// Publish & Subscribe stuff - used to initiate an encryption pass from the test app
       
   498 	static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
       
   499 	TInt r;
       
   500 	TInt i;
       
   501 
       
   502 	TInt swapInstance = KErrNotFound;
       
   503 #if defined (__DEMAND_PAGING__)
       
   504 	swapInstance = SwapInstance();
       
   505 #endif
       
   506 
       
   507 	// **************************************************************************************
       
   508 	// Set up P&S publishers so we can publish the status for our drives
       
   509 	// **************************************************************************************
       
   510 	__KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi, ToUi, ProgressToUi P&S publisher & FromUi P&S observer", iInstance));
       
   511 
       
   512 	for (i = 0; i<DriveCount(iInstance); i++)
       
   513 		{
       
   514 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
       
   515 		TInt driveLetter = iDriveLetterList[i];
       
   516 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(driveLetter)));
       
   517 
       
   518 		// no point setting up P&S for the swap drive
       
   519 		if (driveLetter == -1)
       
   520 			{
       
   521 			__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping P&S for swap partition", iInstance, i));
       
   522 			continue;
       
   523 			}
       
   524 
       
   525 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iStatusToUiProperty, NFE_KEY(driveLetter, KNfeStatusToUiKey));
       
   526 		if (r != KErrNone)
       
   527 			return r;
       
   528 
       
   529 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iToUiProperty, NFE_KEY(driveLetter, KNfeToUiKey));
       
   530 		if (r != KErrNone)
       
   531 			return r;
       
   532 
       
   533 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iProgressToUiProperty, NFE_KEY(driveLetter, KNfeProgressToUiKey));
       
   534 		if (r != KErrNone)
       
   535 			return r;
       
   536 
       
   537 		TPropertyObserver& observer = iFromUiPropertyObserver[i];
       
   538 		observer.iDriveIndex = i;
       
   539 		observer.iMediaExt = this;
       
   540 		observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
       
   541 		if (observer.iPropertySubsRequest == NULL)
       
   542 			return KErrNoMemory;
       
   543 
       
   544 		observer.iPropertyDfc = new TDfc(FromUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
       
   545 		if (observer.iPropertyDfc == NULL)
       
   546 			return KErrNoMemory;
       
   547 		
       
   548 		r = observer.iProperty.Attach(KNfeUID, NFE_KEY(driveLetter, KNfeToThreadKey));
       
   549 		if (r != KErrNone)
       
   550 			return r;
       
   551 		r = observer.iProperty.Define(
       
   552 			RProperty::EInt,
       
   553 			KPassPolicy, 
       
   554 			KPassPolicy);
       
   555 		if (r != KErrNone && r != KErrAlreadyExists)
       
   556 			return r;
       
   557 
       
   558 		r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
       
   559 		if (r != KErrNone)
       
   560 			return r;
       
   561 		}
       
   562 
       
   563 	// **************************************************************************************
       
   564 	// If this instance owns the swap partition,
       
   565 	// set up P&S listeners so we can get status notification events from the other drives
       
   566 	// **************************************************************************************
       
   567 	__KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi P&S observer", iInstance));
       
   568 
       
   569 	for (i = 0; i < (iInstance == swapInstance ? NFE_DRIVECOUNT : -1); i++)
       
   570 		{
       
   571 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
       
   572 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(DriveLetter(i))));
       
   573 
       
   574 		// no point setting up P&S for the swap drive
       
   575 		if (DriveLetter(i) == -1)
       
   576 			{
       
   577 			__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping StatusToUi P&S observer for swap partition", iInstance, i));
       
   578 			continue;
       
   579 			}
       
   580 
       
   581 		__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Setting up StatusToUi P&S observer for drive %c", iInstance, i, (TInt) DriveLetterToAscii(DriveLetter(i))));
       
   582 		TPropertyObserver& observer = iStatusToUiPropertyObserver[i];
       
   583 		observer.iDriveIndex = i;
       
   584 		observer.iMediaExt = this;
       
   585 		observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
       
   586 		if (observer.iPropertySubsRequest == NULL)
       
   587 			return KErrNoMemory;
       
   588 
       
   589 		observer.iPropertyDfc = new TDfc(StatusToUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
       
   590 		if (observer.iPropertyDfc == NULL)
       
   591 			return KErrNoMemory;
       
   592 		
       
   593 		r = observer.iProperty.Attach(KNfeUID, NFE_KEY(DriveLetter(i), KNfeStatusToUiKey));
       
   594 		if (r != KErrNone)
       
   595 			return r;
       
   596 		r = observer.iProperty.Define(
       
   597 			RProperty::EInt,
       
   598 			KPassPolicy, 
       
   599 			KPassPolicy);
       
   600 		if (r != KErrNone && r != KErrAlreadyExists)
       
   601 			return r;
       
   602 
       
   603 		r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
       
   604 		if (r != KErrNone)
       
   605 			return r;
       
   606 		}
       
   607 
       
   608 	return(KErrNone);
       
   609 	}
       
   610 
       
   611 void DMediaDriverNFE::TPropertyObserver::Close()
       
   612 	{
       
   613 	iProperty.Close();
       
   614 	delete iPropertyDfc;
       
   615 	iPropertyDfc = NULL;
       
   616 	delete iPropertySubsRequest;
       
   617 	iPropertySubsRequest = NULL;
       
   618 	}
       
   619 
       
   620 void DMediaDriverNFE::TPropertyObserver::PropertySubsCompleteFn(TAny* aPtr, TInt /*aReason*/)
       
   621 	{
       
   622 	TPropertyObserver* self = (TPropertyObserver*) aPtr;
       
   623 	// Queue a DFC to ensure we're running in the correct thread
       
   624 	self->iPropertyDfc->Enque();
       
   625 	}
       
   626 
       
   627 void DMediaDriverNFE::FromUiPropertyDfcFunction(TAny* aObserver)
       
   628 	{
       
   629 	TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
       
   630 	observer.iMediaExt->FromUiPropertyDfc(observer);
       
   631 	}
       
   632 
       
   633 void DMediaDriverNFE::FromUiPropertyDfc(TPropertyObserver& aObserver)
       
   634 	{
       
   635     // Get the value of request from the UI
       
   636     TInt err = aObserver.iProperty.Get(aObserver.iValue);
       
   637 
       
   638 	TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
       
   639 	__ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
       
   640 
       
   641 	TInt driveLetter = iDriveLetterList[aObserver.iDriveIndex];
       
   642 
       
   643 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::FromUiPropertyDfc() cmd %d driveLetter %c", 
       
   644 		iInstance, aObserver.iValue, (TInt) DriveLetterToAscii(driveLetter)));
       
   645 
       
   646 	// is this our drive letter ?
       
   647 	TInt driveCount = DriveCount(iInstance);
       
   648 	TNfeDriveInfo* driveInfo = NULL;
       
   649 
       
   650 	for (TInt i=0; i<driveCount; i++)
       
   651 		{
       
   652 		TInt myDriveLetter = iDriveLetterList[i];
       
   653 
       
   654 		__KTRACE_PRINT(Kern::Printf("NFE%d: Comparing drive %c with myDrive %c", iInstance, (TInt) DriveLetterToAscii(driveLetter), (TInt) DriveLetterToAscii(myDriveLetter)));
       
   655 
       
   656 		if (myDriveLetter == driveLetter)
       
   657 			{
       
   658 			TInt driveNumber = iDriveList[i];
       
   659 			driveInfo = &iInfo.iDrives[iDriveNumToIndex[driveNumber]];
       
   660 			__KTRACE_PRINT(Kern::Printf("NFE%d: Drive Match found driveNumber %d", iInstance, driveInfo->iLocalDriveNum));
       
   661 
       
   662 			__ASSERT_ALWAYS(driveInfo->iProgressToUiProperty, NFE_FAULT());
       
   663 			((RPropertyRef*) (driveInfo->iProgressToUiProperty))->Set(0); 
       
   664 			// Wake up the possibly waiting client, whether or not the request
       
   665 			// was successfull.
       
   666 			((RPropertyRef*) (driveInfo->iToUiProperty))->Set( err ); // Return value ignored
       
   667 			break;
       
   668 			}
       
   669 		}
       
   670 
       
   671 
       
   672 	__KTRACE_PRINT(Kern::Printf("NFE%d: err %d aObserver.iValue %d swap %x swap state %d", iInstance, err, aObserver.iValue, GetSwapDrive(), GetSwapDrive() ? GetSwapDrive()->Status() : -1));
       
   673 
       
   674 	if (err == KErrNone && aObserver.iValue == ENfeEncryptDisk && driveInfo != NULL)
       
   675 		{
       
   676 		if (driveInfo->Status() == ENfeDecrypted)
       
   677 			{
       
   678 			SetStatus(*driveInfo, ENfeEncrypting);
       
   679 			StartEncrypting();
       
   680 			}
       
   681 		}
       
   682 	if (err == KErrNone && aObserver.iValue == ENfeDecryptDisk && driveInfo != NULL)
       
   683 		{
       
   684 		if (driveInfo->Status() == ENfeEncrypted)
       
   685 			{
       
   686 			SetStatus(*driveInfo, ENfeDecrypting);
       
   687 			StartDecrypting();
       
   688 			}
       
   689 		}
       
   690 	}
       
   691 
       
   692 
       
   693 void DMediaDriverNFE::StatusToUiPropertyDfcFunction(TAny* aObserver)
       
   694 	{
       
   695 	TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
       
   696 	observer.iMediaExt->StatusToUiPropertyDfc(observer);
       
   697 	}
       
   698 
       
   699 void DMediaDriverNFE::StatusToUiPropertyDfc(TPropertyObserver& aObserver)
       
   700 	{
       
   701     // Get the value of request from the UI
       
   702     TInt err = aObserver.iProperty.Get(aObserver.iValue);
       
   703 
       
   704 	TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
       
   705 	__ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
       
   706 
       
   707 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::StatusToUiPropertyDfc() status %d driveLetter %c", 
       
   708 		iInstance, aObserver.iValue, DriveLetter(aObserver.iDriveIndex) >=0 ? DriveLetter(aObserver.iDriveIndex)+'A' : '?'));
       
   709 
       
   710 
       
   711 	__KTRACE_PRINT(Kern::Printf("NFE%d: err %d aObserver.iValue %d swap %x swap state %d", iInstance, err, aObserver.iValue, GetSwapDrive(), GetSwapDrive() ? GetSwapDrive()->Status() : -1));
       
   712 
       
   713 	if (err == KErrNone && (aObserver.iValue == ENfeEncrypted || aObserver.iValue == ENfeEncrypting))
       
   714 		{
       
   715 		// If any drive is being or is already encrypted then we have to encrypt the swap partition...
       
   716 		TNfeDriveInfo* diSwap = GetSwapDrive();
       
   717 		if (diSwap != NULL && diSwap->Status() == ENfeDecrypted)
       
   718 			{
       
   719 			SetStatus(*diSwap, ENfeEncrypting);
       
   720 			StartEncrypting();
       
   721 			}
       
   722 		}
       
   723 	}
       
   724 
       
   725 
       
   726 void DMediaDriverNFE::Close()
       
   727 	{
       
   728 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::Close()", iInstance));
       
   729 	DMediaDriverExtension::Close();
       
   730 	}
       
   731 
       
   732 
       
   733 void DMediaDriverNFE::SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus)
       
   734 	{
       
   735 	if (aStatus != aDi.Status())
       
   736 		{
       
   737 		aDi.SetStatus(aStatus);
       
   738 		__KTRACE_PRINT(Kern::Printf("NFE%d: SetStatus = %s", iInstance, DriveStatus(aDi.Status())));
       
   739 		}
       
   740 	}
       
   741 
       
   742 void TNfeDriveInfo::SetStatus(TNfeDiskStatus aStatus)
       
   743     {
       
   744 	iStatus = aStatus;
       
   745 	if (IsUDADrive())
       
   746 		{
       
   747 		// Update the status pub&sub variable for UI
       
   748 		__ASSERT_ALWAYS(iStatusToUiProperty, NFE_FAULT());
       
   749 		((RPropertyRef*) iStatusToUiProperty)->Set(aStatus);
       
   750 		}
       
   751 	}
       
   752 
       
   753 
       
   754 
       
   755 
       
   756 TInt DMediaDriverNFE::Request(TLocDrvRequest& aReq)
       
   757 	{
       
   758 //	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DoRequest() : Req %d drv %d flags %x pos %lx len %lx", iInstance, reqId, aReq.Drive()->iDriveNumber, aReq.Flags(), aReq.Pos(), aReq.Length()));
       
   759 
       
   760 	TInt r = KErrNotSupported;
       
   761 
       
   762 	TInt reqId = aReq.Id();
       
   763     TNfeDriveInfo& di = iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
   764 
       
   765 	switch (reqId)
       
   766 		{
       
   767 #if defined(__DEMAND_PAGING__)
       
   768 		case DMediaPagingDevice::ERomPageInRequest:
       
   769 			BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
       
   770 			r=HandleRead(aReq);
       
   771 			break;
       
   772 
       
   773 		case DMediaPagingDevice::ECodePageInRequest:
       
   774 			BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
       
   775 			r=HandleRead(aReq);
       
   776 			break;
       
   777 
       
   778 #endif	// __DEMAND_PAGING__
       
   779 
       
   780 		case DLocalDrive::ERead:
       
   781 			r=HandleRead(aReq);
       
   782 			break;
       
   783 
       
   784 		case DLocalDrive::EWrite:
       
   785 			WriteEncryptionStatusToBootSector(di, EFalse);	// a write to the drive clears the finalised state
       
   786 			r=HandleWrite(aReq);
       
   787 			break;
       
   788 
       
   789 		case DLocalDrive::ECaps:
       
   790 			r = HandleCaps(aReq);
       
   791 			break;
       
   792 
       
   793 		case DLocalDrive::EFormat:
       
   794 			r = HandleFormat(aReq);
       
   795 			break;
       
   796 
       
   797 		// API used by T_NFE to query state etc.
       
   798 		case DLocalDrive::EQueryDevice:
       
   799 			switch((TInt) aReq.iArg[0])
       
   800 				{
       
   801 				case EQueryNfeDeviceInfo:
       
   802 					{
       
   803 					TNfeDeviceInfo& deviceInfo = *(TNfeDeviceInfo*) aReq.RemoteDes();
       
   804 					iInfo.iMediaSizeInBytes = iTotalSizeInBytes;
       
   805 					deviceInfo = iInfo;
       
   806 
       
   807 					r = KErrCompletion;
       
   808 					break;
       
   809 					}
       
   810 				case RLocalDrive::EQueryFinaliseDrive:
       
   811 					{
       
   812 //					TLocalDriveFinaliseInfo& finaliseInfo = *(TLocalDriveFinaliseInfo*) aReq.RemoteDes();
       
   813 //					__KTRACE_PRINT(Kern::Printf("NFE%d: EQueryFinaliseDrive iMode %d", iInstance, finaliseInfo.iMode));
       
   814 
       
   815 					// write to boot sector to indicate that the drive has ben finalised
       
   816 					WriteEncryptionStatusToBootSector(di, ETrue);
       
   817 					}
       
   818 				default:
       
   819 					r = KErrNotSupported;
       
   820 					break;
       
   821 				}
       
   822 			break;
       
   823 
       
   824 		default:
       
   825 			r = ForwardRequest(aReq);
       
   826 			break;
       
   827 		}
       
   828 
       
   829 //	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DoRequest() : ret: %d", iInstance, r));
       
   830 
       
   831 	if (!di.iDriveFinalised && iBusy)
       
   832 		{
       
   833 		// Restart the idle timer after processing a request 
       
   834 		iIdleTimer.Cancel();
       
   835 		iTimerDfc.Cancel();
       
   836 		iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
   837 		}
       
   838 
       
   839 	return r;
       
   840 	}
       
   841 
       
   842 /**
       
   843 PartitionInfo()
       
   844 
       
   845     Reads the partition information from the attached drive(s). 
       
   846     Note: this method is also called when a removable card is removed, so can  
       
   847     be used to detect a memory card insertions/removals. Assumes the swap 
       
   848     partition is encrypted if any encrypted FAT drives are found
       
   849 */
       
   850 TInt DMediaDriverNFE::PartitionInfo(TPartitionInfo& aInfo)
       
   851 	{
       
   852 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::PartitionInfo()", iInstance));
       
   853 
       
   854 	TInt r = DoDrivePartitionInfo(aInfo);
       
   855 	__KTRACE_PRINT(Kern::Printf("NFE%d: DoDrivePartitionInfo() r %d", iInstance, r));
       
   856 	if (r != KErrNone)
       
   857 		return r;
       
   858 
       
   859 	__KTRACE_PRINT(Kern::Printf("NFE%d: *** Slave drives partition info ***", iInstance));
       
   860 	__KTRACE_PRINT(Kern::Printf("NFE%d: iMediaSizeInBytes %lx", iInstance, aInfo.iMediaSizeInBytes));
       
   861 	__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionCount %d", iInstance, aInfo.iPartitionCount));
       
   862 	__KTRACE_PRINT(Kern::Printf("NFE%d: ", iInstance));
       
   863 
       
   864 	TInt i;
       
   865 
       
   866 	__ASSERT_DEBUG(aInfo.iPartitionCount <= TNfeDeviceInfo::ENfeMaxPartitionEntries, NFE_FAULT());
       
   867 	for (i=0; i<aInfo.iPartitionCount; i++)
       
   868 		{
       
   869 		TInt driveNum = iDriveList[i];
       
   870 		iDriveNumToIndex[driveNum] = i;
       
   871 
       
   872 		TNfeDriveInfo& di = iInfo.iDrives[i];
       
   873 
       
   874 		di.iDriveFinalised = EFalse;	// a remount clears the finalised state
       
   875 
       
   876 		// Make sure we haven't lost the swap partition
       
   877 		__ASSERT_ALWAYS(!(di.iEntry.iPartitionType == KPartitionTypePagedData && aInfo.iEntry[i].iPartitionType != KPartitionTypePagedData), NFE_FAULT());
       
   878 
       
   879 		// Make a copy of the TPartitionEntry
       
   880 		di.iEntry = aInfo.iEntry[i];
       
   881 
       
   882 
       
   883 		// save the local drive number
       
   884 		di.iLocalDriveNum = driveNum;
       
   885 		di.iDriveLetter = iDriveLetterList[i];
       
   886 
       
   887 		__KTRACE_PRINT(Kern::Printf("NFE%d: DriveNum %d", iInstance, driveNum));
       
   888 		__KTRACE_PRINT(Kern::Printf("NFE%d: DriveLetter %c", iInstance, (TInt) DriveLetterToAscii(di.iDriveLetter)));
       
   889 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionBaseAddr %lX", iInstance, di.iEntry.iPartitionBaseAddr));
       
   890 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionLen %lx", iInstance, di.iEntry.iPartitionLen));
       
   891 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionType %x", iInstance, di.iEntry.iPartitionType));
       
   892 		
       
   893 
       
   894 		// If the drive was removed, reset it's state
       
   895 		if (di.iEntry.iPartitionType == KPartitionTypeEmpty)
       
   896 			{
       
   897 			__KTRACE_PRINT(Kern::Printf("NFE%d: Empty Partition, setting state to ENfeUnmounted", iInstance));
       
   898 			SetStatus(di, ENfeUnmounted);
       
   899 			}
       
   900 
       
   901 		// Is this an unencrypted FAT partition ?
       
   902 		if (di.IsUDADrive())
       
   903 			{
       
   904 			r = Read(di.iLocalDriveNum, di.iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
   905 			if (r != KErrNone)
       
   906 				return r;
       
   907 			CheckBootSector(di);
       
   908 			}
       
   909 		
       
   910 
       
   911 		__KTRACE_PRINT(Kern::Printf("NFE%d: status = %s", iInstance, DriveStatus(di.Status())));
       
   912 
       
   913 		__KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptStartPos %lX", iInstance, di.iEncryptStartPos));
       
   914 		__KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptEndPos %lX", iInstance, di.iEncryptEndPos));
       
   915 		__KTRACE_PRINT(Kern::Printf("NFE%d: ", iInstance));
       
   916 		}
       
   917 
       
   918 
       
   919 
       
   920 #ifdef COMPOSITE_DRIVES
       
   921 	// Accumulate the sizes of consecutive FAT drives & report the accumulated size back in the first FAT partition
       
   922 	for (i=0; i<aInfo.iPartitionCount; i++)
       
   923 		{
       
   924 		aInfo.iEntry[i] = iInfo.iDrives[i].iEntry;
       
   925 
       
   926 		if (iInfo.iDrives[i].IsUDADrive())
       
   927 			{
       
   928 			aInfo.iEntry[i].iPartitionLen = 0;
       
   929 			for (TInt j=i; j<aInfo.iPartitionCount; j++)
       
   930 				{
       
   931 				if (iInfo.iDrives[j].IsUDADrive())
       
   932 					{
       
   933 					aInfo.iEntry[i].iPartitionLen+= iInfo.iDrives[j].iEntry.iPartitionLen;
       
   934 					}
       
   935 				}
       
   936 			iInfo.iDrives[i].iCompositeSize = aInfo.iEntry[i].iPartitionLen;
       
   937 			i = j;
       
   938 			}
       
   939 		}
       
   940 #endif
       
   941 
       
   942 
       
   943 	SetTotalSizeInBytes(aInfo.iMediaSizeInBytes);
       
   944 
       
   945 
       
   946 	return KErrCompletion;	// synchronous completion
       
   947 	}
       
   948 
       
   949 /**
       
   950 HandleCaps() - 
       
   951 
       
   952 Return the Caps for a particular drive
       
   953 
       
   954 Queries the caps from the attached drive, ORs in appropriate paging flags & returns
       
   955 */
       
   956 TInt DMediaDriverNFE::HandleCaps(TLocDrvRequest& aReq)
       
   957 	{
       
   958 	// Get caps from slave drive
       
   959 	// NB if we didn't want to alter anything then we could just call ForwardRequest(aReq);
       
   960 	TBuf8<sizeof(TLocalDriveCapsV6)> slaveCapsBuf;
       
   961 	TLocalDriveCapsV6& slaveCaps = *(TLocalDriveCapsV6*) slaveCapsBuf.Ptr();
       
   962 	slaveCapsBuf.SetMax();
       
   963 	slaveCapsBuf.FillZ();
       
   964 	TInt r = Caps(aReq.Drive()->iDriveNumber, slaveCapsBuf);
       
   965 	if (r != KErrNone)
       
   966 		return r;
       
   967 
       
   968 #ifdef COMPOSITE_DRIVES
       
   969 	TInt driveNum = aReq.Drive()->iDriveNumber;
       
   970 	TInt driveIndex = DriveIndex(driveNum);
       
   971 	if (iInfo.iDrives[driveIndex].iCompositeSize)
       
   972 		slaveCaps.iSize = iInfo.iDrives[driveIndex].iCompositeSize;
       
   973 #endif
       
   974 
       
   975 	// copy slave caps to returned caps
       
   976 	TLocalDriveCapsV6& caps = *(TLocalDriveCapsV6*)aReq.RemoteDes();		
       
   977 	caps = slaveCaps;
       
   978 
       
   979 	// set the paging flags
       
   980 #ifdef __DEMAND_PAGING__
       
   981 	TLocDrv& drive = *aReq.Drive();
       
   982 	if (drive.iPrimaryMedia->iPagingMedia)
       
   983 		caps.iMediaAtt|=KMediaAttPageable;
       
   984 	if (drive.iPagingDrv)
       
   985 		caps.iDriveAtt|=KDriveAttPageable;
       
   986 #endif // __DEMAND_PAGING__
       
   987 
       
   988 	return KErrCompletion;
       
   989 	}
       
   990 
       
   991 
       
   992 /**
       
   993 AdjustRequest() - 
       
   994 
       
   995 Adjusts position & length if a request crosses these boundaries:
       
   996 - the start of the partition (if RLocalDrive::ELocDrvWholeMedia set)
       
   997 - the current encrytion point (iEncryptEndPos) N.B. this will point to the end of the partition 
       
   998   if the drive is fully encrypted
       
   999 
       
  1000 For composite drives, it also adjusts the position, length & drive number as appropriate to cater for 
       
  1001 crossing partition boundaries
       
  1002 
       
  1003 returns ETrue if buffer needs encrypting/decrypting
       
  1004 */
       
  1005 
       
  1006 TBool DMediaDriverNFE::AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen)
       
  1007 	{
       
  1008 #ifdef COMPOSITE_DRIVES
       
  1009 	while (aCurrentPos >= aDriveInfo->iEntry.iPartitionLen)
       
  1010 		{
       
  1011 		aCurrentPos-= aDriveInfo->iEntry.iPartitionLen;
       
  1012 		aDriveInfo++;
       
  1013 		}
       
  1014 	if (aCurrentPos + aCurrentLen > aDriveInfo->iEntry.iPartitionLen)
       
  1015 		aCurrentLen = aDriveInfo->iEntry.iPartitionLen - aCurrentPos;
       
  1016 #endif
       
  1017 
       
  1018 	// do we need to encrypt/decrypt this buffer ?
       
  1019 	TBool encodeBuffer = EFalse;
       
  1020 	
       
  1021 	if ((aDriveInfo->Status() == ENfeEncrypted) || aDriveInfo->Status() == ENfeEncrypting)
       
  1022 		{
       
  1023 //		__ASSERT_DEBUG(aDriveInfo->iEncryptEndPos <= aDriveInfo->iEntry.iPartitionBaseAddr + aDriveInfo->iEntry.iPartitionLen, NFE_FAULT());
       
  1024 
       
  1025 		if (aCurrentPos < aDriveInfo->iEncryptStartPos)
       
  1026 			{
       
  1027 			aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptStartPos - aCurrentPos);
       
  1028 			encodeBuffer = EFalse;
       
  1029 			}
       
  1030 		else if (aCurrentPos < aDriveInfo->iEncryptEndPos)
       
  1031 			{
       
  1032 			aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptEndPos - aCurrentPos);
       
  1033 			encodeBuffer = ETrue;
       
  1034 			}
       
  1035 		else
       
  1036 			{
       
  1037 			encodeBuffer = EFalse;
       
  1038 			}
       
  1039 		}
       
  1040 
       
  1041 	return encodeBuffer;
       
  1042 	}
       
  1043 
       
  1044 
       
  1045 TInt DMediaDriverNFE::HandleRead(TLocDrvRequest& aReq)
       
  1046 	{
       
  1047 	TInt r = KErrNone;
       
  1048 	TInt64 currentPos = aReq.Pos();
       
  1049 	TInt64 remainingLength = aReq.Length();
       
  1050 	TInt desPos = 0;
       
  1051 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1052 
       
  1053 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleRead pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1054 
       
  1055 
       
  1056 	di->iReadRequestCount++;
       
  1057 
       
  1058 	if (aReq.Flags() & TLocDrvRequest::ECodePaging)
       
  1059 		di->iCodePagingRequesCount++;
       
  1060 	if (aReq.Flags() & TLocDrvRequest::EDataPaging)
       
  1061 		di->iDataPagingReadRequestCount++;
       
  1062 
       
  1063 	
       
  1064 	// just forward the request if the drive is not encrypted
       
  1065 	if (di->Status() == ENfeDecrypted)
       
  1066 		return ForwardRequest(aReq);
       
  1067 
       
  1068 	
       
  1069 	while(remainingLength)
       
  1070 		{
       
  1071 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1072 
       
  1073 		TBool decryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1074 
       
  1075 		// Read from attached drive
       
  1076 #ifdef __DEMAND_PAGING__
       
  1077 		if (DMediaPagingDevice::PagingRequest(aReq))
       
  1078 			r = ReadPaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1079 		else
       
  1080 #endif
       
  1081 		r = Read(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1082 		if(r != KErrNone)
       
  1083 			break;
       
  1084 
       
  1085 		TPtr8 des(iBuffer, I64LOW(currentLength), I64LOW(currentLength));
       
  1086 
       
  1087 		// decrypt buffer
       
  1088 		if (decryptBuffer)
       
  1089 			DecryptBuffer(des);
       
  1090 
       
  1091 		//  write back to user
       
  1092 		r = aReq.WriteRemote(&des, desPos);
       
  1093 		if(r != KErrNone)
       
  1094 			break;
       
  1095 
       
  1096 		remainingLength-= currentLength;
       
  1097 		currentPos+= currentLength;
       
  1098 		desPos+= I64LOW(currentLength);
       
  1099 		}
       
  1100 
       
  1101 	return r == KErrNone ? KErrCompletion : r;
       
  1102 	}
       
  1103 
       
  1104 TInt DMediaDriverNFE::HandleWrite(TLocDrvRequest& aReq)
       
  1105 	{
       
  1106 	TInt r = KErrNone;
       
  1107 	TInt64 currentPos =  aReq.Pos();
       
  1108 	TInt64 remainingLength = aReq.Length();
       
  1109 	TInt desPos = 0;
       
  1110 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1111 
       
  1112 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleWrite pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1113 
       
  1114 
       
  1115 	di->iWriteRequestCount++;
       
  1116 	if (aReq.Flags() & TLocDrvRequest::EDataPaging)
       
  1117 		di->iDataPagingWriteRequestCount++;
       
  1118 	
       
  1119 
       
  1120 	// just forward the request if the drive is not encrypted
       
  1121 	if (di->Status() == ENfeDecrypted)
       
  1122 		return ForwardRequest(aReq);
       
  1123 
       
  1124 	while(remainingLength)
       
  1125 		{
       
  1126 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1127 
       
  1128 		TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1129 
       
  1130 		// read from user
       
  1131 		TPtr8 des(iBuffer,0,I64LOW(currentLength));
       
  1132 		r = aReq.ReadRemote(&des, desPos);
       
  1133 		if(r != KErrNone)
       
  1134 			break;
       
  1135 		
       
  1136 		// get the length of data read from the user in case user's
       
  1137 		// descriptor is shorter than advertised
       
  1138 		currentLength = des.Length();
       
  1139 		if (currentLength == 0)
       
  1140 			break;
       
  1141 
       
  1142 		// writing to sector zero ?
       
  1143 		if (currentPos >= di->iEntry.iPartitionBaseAddr && 
       
  1144 			currentPos < di->iEntry.iPartitionBaseAddr + KSectorSize && 
       
  1145 			di->IsUDADrive())
       
  1146 			{
       
  1147 			__KTRACE_PRINT(Kern::Printf("NFE%d: Write to sector #0 detected", iInstance));
       
  1148 
       
  1149 
       
  1150 			TUint8* bootSector = iBuffer;
       
  1151 			TUint8 bootSectorBuffer[KSectorSize];
       
  1152 			// writing partial sector ?
       
  1153 			if (currentPos > di->iEntry.iPartitionBaseAddr || currentLength < KSectorSize)
       
  1154 				{
       
  1155 				bootSector = bootSectorBuffer;
       
  1156 				r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) bootSector, KSectorSize);
       
  1157 				if(r != KErrNone)
       
  1158 					break;
       
  1159 				TInt64 readLen = KSectorSize;
       
  1160 				TBool encryptBuffer = AdjustRequest(di, di->iEntry.iPartitionBaseAddr, readLen);
       
  1161 				if (encryptBuffer)
       
  1162 					{
       
  1163 					TPtr8 des(bootSectorBuffer,KSectorSize,KSectorSize);
       
  1164 					DecryptBuffer(des);
       
  1165 					}
       
  1166 				TInt sectorOffset = (TInt) (currentPos - di->iEntry.iPartitionBaseAddr);
       
  1167 				TInt64 copyLen = currentLength;
       
  1168 				if (copyLen > KSectorSize-sectorOffset)
       
  1169 					copyLen = KSectorSize-sectorOffset;
       
  1170 				memcpy(bootSectorBuffer+sectorOffset, iBuffer, (TInt) copyLen);
       
  1171 				}
       
  1172 
       
  1173 			if ((di->Status() == ENfeUnmounted || di->Status() == ENfeCorrupted) && 
       
  1174 				ValidBootSector(bootSector))
       
  1175 				{
       
  1176 				__KTRACE_PRINT(Kern::Printf("NFE%d: Setting status to ENfeDecrypted", iInstance ));
       
  1177 				di->SetStatus(ENfeDecrypted);
       
  1178 				}
       
  1179 			di->iUniqueID = VolumeId(bootSector);		// update the Volume ID
       
  1180 			__KTRACE_PRINT(Kern::Printf("NFE%d: Setting Volume ID to %08X", iInstance, di->iUniqueID ));
       
  1181 			TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1182 			if (di->Status() == ENfeEncrypting || di->Status() == ENfeDecrypting)
       
  1183 				{
       
  1184 				__KTRACE_PRINT(Kern::Printf("NFE%d: Adding NFE status record to boot sector", iInstance ));
       
  1185 				bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
       
  1186 				bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
       
  1187 				bootSectorStatus->iStatus = di->Status();
       
  1188 				bootSectorStatus->iFinalised = EFalse;
       
  1189 				}
       
  1190 			}
       
  1191 
       
  1192 		// encrypt the buffer
       
  1193 		if (encryptBuffer)
       
  1194 			EncryptBuffer(des);
       
  1195 
       
  1196 		// write the data to the attached drive
       
  1197 #ifdef __DEMAND_PAGING__
       
  1198 		if (DMediaPagingDevice::PagingRequest(aReq))
       
  1199 			r = WritePaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1200 		else
       
  1201 #endif
       
  1202 		r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1203 		if(r != KErrNone)
       
  1204 			break;
       
  1205 
       
  1206 		remainingLength-= currentLength;
       
  1207 		currentPos+= currentLength;
       
  1208 		desPos+= I64LOW(currentLength);
       
  1209 		}
       
  1210 
       
  1211 	return r == KErrNone ? KErrCompletion : r;
       
  1212 	}
       
  1213 
       
  1214 TInt DMediaDriverNFE::HandleFormat(TLocDrvRequest& aReq)
       
  1215 	{
       
  1216 	TInt r = KErrNone;
       
  1217 	TInt64 currentPos =  aReq.Pos();
       
  1218 	TInt64 remainingLength = aReq.Length();
       
  1219 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1220 
       
  1221 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleFormat pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1222 
       
  1223 
       
  1224 	// just forward the request if the drive is not encrypted
       
  1225 	if (di->Status() == ENfeDecrypted)
       
  1226 		return ForwardRequest(aReq);
       
  1227 
       
  1228 	// otherwise create a buffer containing NULLs, encrypt it and write that to the attached drive
       
  1229 	while(remainingLength && r == KErrNone)
       
  1230 		{
       
  1231 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1232 
       
  1233 		TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1234 
       
  1235 		memclr(iBuffer, KBufSize);
       
  1236 		TPtr8 des(iBuffer,KBufSize,KBufSize);
       
  1237 
       
  1238 		if (encryptBuffer)
       
  1239 			EncryptBuffer(des);
       
  1240 		
       
  1241 		r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1242 		if(r != KErrNone)
       
  1243 			break;
       
  1244 
       
  1245 		remainingLength-= currentLength;
       
  1246 		currentPos+= currentLength;
       
  1247 		}
       
  1248 
       
  1249 	return r == KErrNone ? KErrCompletion : r;
       
  1250 	}
       
  1251 
       
  1252 
       
  1253 void DMediaDriverNFE::EncryptBuffer(TDes8& aBuffer)
       
  1254 	{
       
  1255 	TInt len = aBuffer.Length();
       
  1256 	for(TInt i=0; i<len; i++)
       
  1257 		aBuffer[i] = EncryptByte(aBuffer[i]);
       
  1258 	}
       
  1259 
       
  1260 void DMediaDriverNFE::DecryptBuffer(TDes8& aBuffer)
       
  1261 	{
       
  1262 	TInt len = aBuffer.Length();
       
  1263 	for(TInt i=0; i<len; i++)
       
  1264 		aBuffer[i] = DecryptByte(aBuffer[i]);
       
  1265 	}
       
  1266 
       
  1267 
       
  1268 TNfeDriveInfo* DMediaDriverNFE::GetSwapDrive()
       
  1269 	{
       
  1270 	for (TInt i=0; i<iInfo.iDriveCount; i++)
       
  1271 		{
       
  1272 		TNfeDriveInfo& di = iInfo.iDrives[i];
       
  1273 		if (di.iEntry.iPartitionType == KPartitionTypePagedData)
       
  1274 			{
       
  1275 			return &di;
       
  1276 			}
       
  1277 		}
       
  1278 	return NULL;	// swap drive not found
       
  1279 	}
       
  1280 
       
  1281 /**
       
  1282 Get the first/next drive to encrypt 
       
  1283 */
       
  1284 
       
  1285 TNfeDriveInfo* DMediaDriverNFE::NextDrive()
       
  1286 	{
       
  1287 	for (iDriveIndex = 0; iDriveIndex<iInfo.iDriveCount; iDriveIndex++)
       
  1288 		{
       
  1289 		TNfeDriveInfo& di = iInfo.iDrives[iDriveIndex];
       
  1290 		TNfeDiskStatus status = iInfo.iDrives[iDriveIndex].Status();
       
  1291 		if (status == ENfeEncrypting || status == ENfeDecrypting)
       
  1292 			{
       
  1293 			di.iEncryptStartPos = di.iEncryptEndPos = di.iEntry.iPartitionBaseAddr;
       
  1294 
       
  1295 			// write to boot sector to indicate we are encrypting/decrypting this drive
       
  1296 			WriteEncryptionStatusToBootSector(di);
       
  1297 
       
  1298 			return &di;
       
  1299 			}
       
  1300 		}
       
  1301 	__KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting / decrypting", iInstance));
       
  1302 	iBusy = EFalse;
       
  1303 	return NULL;
       
  1304 	}
       
  1305 
       
  1306 
       
  1307 /** 
       
  1308 Finds the first unencrypted drive & kicks off the idle timer - 
       
  1309 when this expires the encryption of the drive will start
       
  1310 */
       
  1311 void DMediaDriverNFE::StartEncrypting()
       
  1312 	{
       
  1313 	// start encrypting if not already doing so
       
  1314 	if (!iBusy)
       
  1315 		{
       
  1316 		iBusy = ETrue;
       
  1317 		TNfeDriveInfo* di = NextDrive();
       
  1318 		if (di)
       
  1319 			{
       
  1320 			__KTRACE_PRINT(Kern::Printf("NFE%d: Start encrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1321 			iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1322 			}
       
  1323 		}
       
  1324 	}
       
  1325 
       
  1326 /** 
       
  1327 Finds the first unencrypted drive & kicks off the idle timer - 
       
  1328 when this expires the encryption of the drive will start
       
  1329 */
       
  1330 void DMediaDriverNFE::StartDecrypting()
       
  1331 	{
       
  1332 	// start encrypting if not already doing so
       
  1333 	if (!iBusy)
       
  1334 		{
       
  1335 		iBusy = ETrue;
       
  1336 		TNfeDriveInfo* di = NextDrive();
       
  1337 		if (di)
       
  1338 			{
       
  1339 			__KTRACE_PRINT(Kern::Printf("NFE%d: Start decrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1340 			iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1341 			}
       
  1342 		}
       
  1343 	}
       
  1344 
       
  1345 /**
       
  1346 Idle timer callback
       
  1347 Kicks off a DFC to ensure we are running in the correct thread
       
  1348 */
       
  1349 void DMediaDriverNFE::IdleTimerCallBack(TAny* aMediaDriver)
       
  1350 	{
       
  1351 	((DMediaDriverNFE*)aMediaDriver)->iTimerDfc.Add();
       
  1352 	}
       
  1353 
       
  1354 /**
       
  1355 Idle timer DFC
       
  1356 */
       
  1357 void DMediaDriverNFE::TimerDfcFunction(TAny* aMediaDriver)
       
  1358 	{
       
  1359 	((DMediaDriverNFE*) aMediaDriver)->HandleDiskContent();
       
  1360 	}
       
  1361 
       
  1362 
       
  1363 TBool DMediaDriverNFE::ValidBootSector(TUint8* aBuffer)
       
  1364 	{
       
  1365 	if (aBuffer[0] == 0xEB || aBuffer[0] == 0xE9)
       
  1366 		return ETrue;
       
  1367 	else
       
  1368 		return EFalse;
       
  1369 	}
       
  1370 
       
  1371 
       
  1372 TUint32 DMediaDriverNFE::VolumeId(TUint8* aBuffer)
       
  1373 	{
       
  1374 	TUint16 rootDirEntries;
       
  1375 	TUint32 uniqueID;   
       
  1376     memcpy(&rootDirEntries,&aBuffer[17], 2);	// 17   TUint16 iRootDirEntries
       
  1377 	TBool fat32 = rootDirEntries == 0;
       
  1378 	TInt pos = fat32 ? 67 : 39;		// get position of VolumeID
       
  1379 	memcpy(&uniqueID,&aBuffer[pos],4);
       
  1380 	return uniqueID;
       
  1381 	}
       
  1382 
       
  1383 void DMediaDriverNFE::CheckBootSector(TNfeDriveInfo &aDi)
       
  1384 	{
       
  1385 	TNfeDiskStatus  fatBootSectorStatus = ENfeDecrypted;
       
  1386 
       
  1387 	// Try to determine whether the FAT boot sector is encypted
       
  1388 	if (ValidBootSector(iBuffer))
       
  1389 		{
       
  1390 		fatBootSectorStatus = ENfeDecrypted;
       
  1391 		__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is decrypted", iInstance));
       
  1392 		}
       
  1393 	else
       
  1394 		{
       
  1395 		TPtr8 des(iBuffer, KSectorSize, KSectorSize);
       
  1396 		DecryptBuffer(des);
       
  1397 		if (ValidBootSector(iBuffer))
       
  1398 			{
       
  1399 			__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is encrypted", iInstance));
       
  1400 			fatBootSectorStatus = ENfeEncrypted;
       
  1401 			}
       
  1402 		else
       
  1403 			{
       
  1404 			__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is corrupted", iInstance));
       
  1405 			fatBootSectorStatus = ENfeCorrupted;
       
  1406 			}
       
  1407 		}
       
  1408 
       
  1409 	__KTRACE_PRINT(Kern::Printf("NFE%d: fatBootSectorStatus %d", iInstance, fatBootSectorStatus));
       
  1410 
       
  1411 	// Find out whether the volume has changed
       
  1412 	TUint32 uniqueID = VolumeId(iBuffer);   
       
  1413 	TBool volumeChanged = uniqueID != aDi.iUniqueID;
       
  1414 	__KTRACE_PRINT(Kern::Printf("NFE%d: Old Volume ID %08X", iInstance, aDi.iUniqueID));
       
  1415 	__KTRACE_PRINT(Kern::Printf("NFE%d: New Volume ID %08X", iInstance, uniqueID));
       
  1416 	__KTRACE_PRINT(Kern::Printf("NFE%d: volumeChanged %d", iInstance, volumeChanged));
       
  1417 	aDi.iUniqueID = uniqueID;
       
  1418 
       
  1419 
       
  1420 
       
  1421 	TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1422 
       
  1423 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iSignature %08X", iInstance, bootSectorStatus->iSignature));
       
  1424 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iStatus %d", iInstance, bootSectorStatus->iStatus));
       
  1425 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iEncryptEndPos %lx", iInstance, bootSectorStatus->iEncryptEndPos));
       
  1426 
       
  1427 
       
  1428 	/*
       
  1429 	If there IS NFE info in the boot sector, restore the encryption settings - 
       
  1430 	unless the 'finalised' flag is clear which indicates that the media was removed or power was lost
       
  1431 	while encrypting the device...
       
  1432 
       
  1433 	If there is no NFE info in the boot sector and there has been a volume change, then we can decide  
       
  1434 	whether the drive is encrypted/decrypted/corrupt by examining the boot sector
       
  1435 	*/
       
  1436 	if (volumeChanged && 
       
  1437 		fatBootSectorStatus != ENfeCorrupted &&
       
  1438 		bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
       
  1439 		!bootSectorStatus->iFinalised)
       
  1440 		{
       
  1441 		SetStatus(aDi, ENfeCorrupted);
       
  1442 		}
       
  1443 	else if (volumeChanged && 
       
  1444 		fatBootSectorStatus != ENfeCorrupted &&
       
  1445 		bootSectorStatus->iFinalised &&
       
  1446 		bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
       
  1447 		(bootSectorStatus->iStatus == ENfeDecrypting || bootSectorStatus->iStatus == ENfeEncrypting))
       
  1448 		{
       
  1449 		SetStatus(aDi, bootSectorStatus->iStatus);
       
  1450 		aDi.iEncryptEndPos = bootSectorStatus->iEncryptEndPos;
       
  1451 
       
  1452 		// write to boot sector to indicate we are no longer finalised
       
  1453 		WriteEncryptionStatusToBootSector(aDi, EFalse);	
       
  1454 
       
  1455 		iBusy = ETrue;
       
  1456 		}
       
  1457 	else if (volumeChanged || aDi.Status() == ENfeUnmounted)
       
  1458 		{
       
  1459 		SetStatus(aDi, fatBootSectorStatus);
       
  1460 		if (aDi.Status() == ENfeEncrypted)
       
  1461 			{
       
  1462 			aDi.iEncryptStartPos = aDi.iEntry.iPartitionBaseAddr;
       
  1463 			aDi.iEncryptEndPos = aDi.iEntry.iPartitionBaseAddr + aDi.iEntry.iPartitionLen;
       
  1464 			}
       
  1465 		}
       
  1466 	}
       
  1467 
       
  1468 
       
  1469 TInt DMediaDriverNFE::WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised)
       
  1470 	{
       
  1471 	if (!aDi.IsUDADrive())
       
  1472 		return KErrNone;
       
  1473 
       
  1474 	if (aDi.iDriveFinalised == aFinalised)
       
  1475 		return KErrNone;
       
  1476 
       
  1477 	TNfeDiskStatus status = aDi.Status();
       
  1478 
       
  1479 	TInt64 currentPos = aDi.iEntry.iPartitionBaseAddr;
       
  1480 	TInt64 currentLen = KSectorSize;
       
  1481 	TNfeDriveInfo* di = &aDi;
       
  1482 	TBool encodeBuffer = EFalse;
       
  1483 
       
  1484 	if (status == ENfeEncrypting || status == ENfeEncrypted || status == ENfeDecrypting)
       
  1485 		encodeBuffer = AdjustRequest(di, currentPos, currentLen);
       
  1486 
       
  1487 
       
  1488 	TInt r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1489 	if (r != KErrNone)
       
  1490 		return r;
       
  1491 	TPtr8 des(iBuffer, I64LOW(currentLen), I64LOW(currentLen));
       
  1492 
       
  1493 	if (encodeBuffer)
       
  1494 		DecryptBuffer(des);
       
  1495 
       
  1496 
       
  1497 	TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1498 
       
  1499 	if (status == ENfeEncrypting || status == ENfeDecrypting)
       
  1500 		{
       
  1501 		bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
       
  1502 		bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
       
  1503 		bootSectorStatus->iStatus = status;
       
  1504 		bootSectorStatus->iFinalised = aFinalised;
       
  1505 		}
       
  1506 	else
       
  1507 		{
       
  1508 		bootSectorStatus->iSignature = 0;
       
  1509 		bootSectorStatus->iEncryptEndPos = 0;
       
  1510 		bootSectorStatus->iStatus = ENfeUnmounted;
       
  1511 		bootSectorStatus->iFinalised = EFalse;
       
  1512 		}
       
  1513 
       
  1514 	if (encodeBuffer)
       
  1515 		EncryptBuffer(des);
       
  1516 
       
  1517 
       
  1518 	r = Write(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1519 	return r;
       
  1520 	}
       
  1521 
       
  1522 
       
  1523 /**
       
  1524 HandleDiskContent - 
       
  1525 
       
  1526 Called from Idle timer DFC
       
  1527 
       
  1528 Starts encrypting the current drive (iDrives[iDriveIndex]) from the current encryption position (iEncryptEndPos)
       
  1529 */
       
  1530 TInt DMediaDriverNFE::HandleDiskContent()
       
  1531 	{
       
  1532 	TNfeDriveInfo* di = &iInfo.iDrives[iDriveIndex];
       
  1533 
       
  1534 	__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d at pos %lx", iInstance, di->iLocalDriveNum, di->iEncryptEndPos));
       
  1535 
       
  1536 	if (di->iDriveFinalised)
       
  1537 		{
       
  1538 	    __KTRACE_PRINT(Kern::Printf("HandleDiskContent aborting as drive has been finalised", iInstance));
       
  1539 		return KErrNone;
       
  1540 		}
       
  1541 
       
  1542 //	TInt KBackgroundPriority = 7;						//*test*
       
  1543 //	Kern::SetThreadPriority(KBackgroundPriority);		//*test*
       
  1544 
       
  1545 	TInt r = KErrNone;
       
  1546 	for (;;)
       
  1547 		{
       
  1548 		// If we've finished encryting this drive, change the state and move on to the next drive
       
  1549 		if (r != KErrNone || di->iEncryptEndPos >= di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen)
       
  1550 			{
       
  1551 			if (di->Status() == ENfeEncrypting)
       
  1552 				{
       
  1553 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1554 				SetStatus(*di,  r == KErrNone ? ENfeEncrypted : ENfeCorrupted);
       
  1555 				}
       
  1556 			if (di->Status() == ENfeDecrypting)
       
  1557 				{
       
  1558 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished decrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1559 				SetStatus(*di,  r == KErrNone ? ENfeDecrypted : ENfeCorrupted);
       
  1560 				}
       
  1561 			
       
  1562 			// write to boot sector to indicate we have finished encrypting/decrypting this drive
       
  1563 			r = WriteEncryptionStatusToBootSector(*di);
       
  1564 
       
  1565 			di = NextDrive();
       
  1566 			if (di == NULL)
       
  1567 				{
       
  1568 				r = KErrCompletion;
       
  1569 				break;
       
  1570 				}
       
  1571 			__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1572 			}
       
  1573 
       
  1574 		// If this media or any of the attached media are busy, stop encrypting & wait for the next idle timeout
       
  1575 		if (MediaBusy(di->iLocalDriveNum))
       
  1576 			{
       
  1577 			__KTRACE_PRINT(Kern::Printf("NFE%d: Media is busy !!!", iInstance));
       
  1578 			r = KErrNone;	// goto sleep & wait for another timer event
       
  1579 			break;
       
  1580 			}
       
  1581 
       
  1582 		TInt64& pos = di->iEncryptEndPos;
       
  1583 		TInt64 partitionEnd = di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen;
       
  1584 		TInt len = (TInt) Min (partitionEnd - pos, KBufSize);
       
  1585 
       
  1586 #if defined(TRACE_ENABLED)
       
  1587 		// print position every 1/16 of the partition size
       
  1588 		TInt64 printPos = Max((di->iEntry.iPartitionLen >> 4) & ~(KBufSize-1), KBufSize);
       
  1589 		if (((di->iEncryptEndPos - di->iEncryptStartPos)% printPos) == 0) 
       
  1590 			__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1591 #endif
       
  1592 //		__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1593 
       
  1594 
       
  1595 		// Read a buffer, encrypt it, and then write it back
       
  1596 		// retry in case of media change
       
  1597 		const TInt KRetries = 5;
       
  1598 		r = KErrNotReady;
       
  1599 		for (TInt i=0; r == KErrNotReady && i < KRetries; i++)
       
  1600 			{
       
  1601 			r = Read(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1602 			if (r != KErrNone)
       
  1603 				continue;
       
  1604 
       
  1605 			TPtr8 des(iBuffer,len,len);
       
  1606 			if (di->Status() == ENfeEncrypting)
       
  1607 				EncryptBuffer(des);
       
  1608 			else
       
  1609 				DecryptBuffer(des);
       
  1610 			
       
  1611 			r = Write(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1612 			}
       
  1613 
       
  1614 		if (r == KErrNone)
       
  1615 			pos+= len;
       
  1616 
       
  1617 		if (di->iProgressToUiProperty)	// no iProgressToUiProperty for swap drive
       
  1618 			{
       
  1619 			TInt progress = (TInt) (KNfeDiskOpReady * (pos - di->iEntry.iPartitionBaseAddr) / di->iEntry.iPartitionLen);
       
  1620 //			__KTRACE_PRINT(Kern::Printf("NFE%d: Progess %d ", progress));
       
  1621 			((RPropertyRef*) (di->iProgressToUiProperty))->Set( progress ); // Return value ignored
       
  1622 			}
       
  1623 		}
       
  1624 	
       
  1625 	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleDiskContent returned %d", iInstance, r));
       
  1626 
       
  1627 	// If not completed, start the idle timer & try again later
       
  1628 	if (r != KErrCompletion)
       
  1629 		iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1630 
       
  1631 //	Kern::SetThreadPriority(KNfeThreadPriority);	//*test*
       
  1632 	
       
  1633 	return r;
       
  1634 	}
       
  1635 
       
  1636 
       
  1637 
       
  1638 DECLARE_EXTENSION_PDD()
       
  1639 	{
       
  1640 	__KTRACE_PRINT(Kern::Printf("DECLARE_EXTENSION_PDD()"));
       
  1641 	return new DPhysicalDeviceMediaNFE;
       
  1642 	}
       
  1643 
       
  1644 DECLARE_STANDARD_EXTENSION()
       
  1645 	{
       
  1646 	__KTRACE_PRINT(Kern::Printf("DECLARE_STANDARD_EXTENSION()"));
       
  1647 
       
  1648 
       
  1649 	// Create the media driver factory object and register this with the kernel
       
  1650 	__KTRACE_PRINT(Kern::Printf("Creating NFE PDD"));
       
  1651 	DPhysicalDeviceMediaNFE* device = new DPhysicalDeviceMediaNFE;
       
  1652 	if (device == NULL)
       
  1653 		return KErrNoMemory;
       
  1654 	TInt r = Kern::InstallPhysicalDevice(device);
       
  1655 	__KTRACE_PRINT(Kern::Printf("Installing NFE PDD in extension init - name %s r:%d", NFE_DRIVENAME, r));
       
  1656 	if (r != KErrNone)
       
  1657 		return r;
       
  1658 
       
  1659 	TInt swapInstance = KErrNotFound;
       
  1660 #if defined (__DEMAND_PAGING__)
       
  1661 	swapInstance = SwapInstance();
       
  1662 #endif
       
  1663 
       
  1664 	DPrimaryMediaExt* primaryMedia[NFE_INSTANCE_COUNT];
       
  1665 	TInt instance;
       
  1666 
       
  1667 	for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1668 		{
       
  1669 		// Register this media device & define which drives we want to attach to.
       
  1670 		// These drives must already be registered with the local media subsystem
       
  1671 		// i.e. this media's kernel extension must be defined AFTER any attached
       
  1672 		// media's kernel extension in the appropriate .IBY file
       
  1673 		__KTRACE_PRINT(Kern::Printf("NFE%d: Creating NFE primary media", instance));
       
  1674 		DPrimaryMediaExt* pM = new DPrimaryMediaExt(instance);
       
  1675 		if (pM == NULL)
       
  1676 			return KErrNoMemory;
       
  1677 		primaryMedia[instance] = pM;
       
  1678 
       
  1679 		_LIT(KMediaThreadName,"NfeThread?");
       
  1680 		HBuf* pMediaThreadName = HBuf::New(KMediaThreadName);
       
  1681 		(*pMediaThreadName)[9] = (TUint8) ('0' + (TUint8) instance);
       
  1682 
       
  1683 		TInt r = Kern::DfcQInit(&pM->iNfeDfcQ,KNfeThreadPriority,pMediaThreadName);
       
  1684 		if (r != KErrNone)
       
  1685 			return r;
       
  1686 
       
  1687 #ifdef CPU_AFFINITY_ANY
       
  1688 		NKern::ThreadSetCpuAffinity((NThread*)(pM->iNfeDfcQ.iThread), KCpuAffinityAny);
       
  1689 #endif
       
  1690 		
       
  1691 
       
  1692 		pM->iDfcQ = &pM->iNfeDfcQ;
       
  1693 		pM->iMsgQ.Receive();
       
  1694 
       
  1695 
       
  1696 		const TInt* driveList = DriveList(instance);
       
  1697 		TInt driveCount = DriveCount(instance);
       
  1698 
       
  1699 		TBuf<4> driveName(_L("NFE?"));
       
  1700 		driveName[3] = (TUint8) ('0' + (TUint8) instance);
       
  1701 
       
  1702 		
       
  1703 		r = LocDrv::RegisterMediaDevice(
       
  1704 			MEDIA_DEVICE_NFE, 
       
  1705 			driveCount, driveList,
       
  1706 			pM, NFE_NUMMEDIA, driveName);
       
  1707 		if (r != KErrNone)
       
  1708 			return r;
       
  1709 
       
  1710 
       
  1711 #if defined (__DEMAND_PAGING__)
       
  1712 		if (PagingType(instance))
       
  1713 			{
       
  1714 			// Define which of the drives we have already attached to have code or data paging enabled 
       
  1715 			const TInt* pageDriveList = PageDriveList(instance);
       
  1716 			TInt pageDriveCount = PageDriveCount(instance);
       
  1717 
       
  1718 			r = LocDrv::RegisterPagingDevice(pM,pageDriveList,pageDriveCount,PagingType(instance),SECTOR_SHIFT,NFE_NUM_PAGES);
       
  1719 			__KTRACE_PRINT(Kern::Printf("NFE%d: Installing NFE PagingDevice in extension init - r:%d", pM->iInstance, r));
       
  1720 			// Ignore error if demand paging not supported by kernel
       
  1721 			if (r == KErrNotSupported)
       
  1722 				r = KErrNone;
       
  1723 			if (r != KErrNone)
       
  1724 				return r;
       
  1725 			}
       
  1726 
       
  1727 
       
  1728 #endif	// __NAND_DEMAND_PAGING__
       
  1729 
       
  1730 		/*
       
  1731 		If there is a swap partition we need to make sure all instances have their PartitionInfo() called
       
  1732 		so that we can flag the swap partition as 'encrypted' if there are any encrypted drives at all
       
  1733 		*/
       
  1734 		if (swapInstance != KErrNotFound)
       
  1735 			{
       
  1736 			TBuf8<sizeof(TLocalDriveCapsV6)> capsBuf;
       
  1737 			capsBuf.SetMax();
       
  1738 			capsBuf.FillZ();
       
  1739 			DLocalDrive::Caps(driveList[0], capsBuf);
       
  1740 			}
       
  1741 		}
       
  1742 		
       
  1743 
       
  1744 	// If we encounter an encrypted drive belonging to ANY NFE instance, then assume the swap partition is 
       
  1745 	// encrypted too. We need to do this because the swap partition has no equivalent of the boot sector
       
  1746 	if (swapInstance != KErrNotFound)
       
  1747 		{
       
  1748 		__KTRACE_PRINT(Kern::Printf("NFE: Searching for encrypted drives to determine whether swap partition should be encrypted..."));
       
  1749 		TBool encryptedDriveFound = EFalse;
       
  1750 		TNfeDriveInfo* swapDriveInfo = NULL;
       
  1751 		for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1752 			{
       
  1753 			DPrimaryMediaExt* pM = primaryMedia[instance];
       
  1754 			DMediaDriverNFE* mediaDriver = (DMediaDriverNFE*) pM->iDriver;
       
  1755 			__ASSERT_ALWAYS(mediaDriver, NFE_FAULT());
       
  1756 
       
  1757 			if (swapDriveInfo == NULL)
       
  1758 				swapDriveInfo = mediaDriver->GetSwapDrive();
       
  1759 
       
  1760 			for (TInt i=0; i<mediaDriver->iInfo.iDriveCount; i++)
       
  1761 				{
       
  1762 				TNfeDriveInfo& di = mediaDriver->iInfo.iDrives[i];
       
  1763 				__KTRACE_PRINT(Kern::Printf("NFE%d: Testing drive %d DriveLetter %c status %s", 
       
  1764 					instance, di.iLocalDriveNum, (TInt) DriveLetterToAscii(di.iDriveLetter), DriveStatus(di.Status()) ));
       
  1765 				if (di.Status() == ENfeEncrypted || di.Status() == ENfeEncrypting)
       
  1766 					encryptedDriveFound = ETrue;
       
  1767 				}
       
  1768 			}
       
  1769 		if (swapDriveInfo)
       
  1770 			{
       
  1771 			swapDriveInfo->SetStatus(encryptedDriveFound ? ENfeEncrypted : ENfeDecrypted);
       
  1772 			swapDriveInfo->iEncryptEndPos = swapDriveInfo->iEntry.iPartitionBaseAddr + swapDriveInfo->iEntry.iPartitionLen;
       
  1773 
       
  1774 			__KTRACE_PRINT(Kern::Printf("NFE: Setting swap partition state to %s...", DriveStatus(swapDriveInfo->Status())));
       
  1775 			}
       
  1776 		}
       
  1777 
       
  1778 
       
  1779 	return r;
       
  1780 	}
       
  1781 
       
  1782