kerneltest/e32test/mediaext/d_nfe.cpp
branchRCL_3
changeset 42 a179b74831c9
child 43 c1f20ce4abcf
equal deleted inserted replaced
41:0ffb4e86fcc9 42:a179b74831c9
       
     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 #define TRACE_ENABLED	//*test*
       
    26 #else
       
    27 #endif
       
    28 
       
    29 #if defined(TRACE_ENABLED)
       
    30 #define __KTRACE_PRINT(p) {p;}
       
    31 #else
       
    32 #define __KTRACE_PRINT(p)
       
    33 #endif
       
    34 
       
    35 
       
    36 
       
    37 
       
    38 // Variant parameters for test Media Extension Driver
       
    39 
       
    40 
       
    41 const TInt KNfeThreadPriority = 24;	        // same as file server
       
    42 const TInt KNfeDiskOpReady = 100;       //100%
       
    43 //const TInt KNfeDiskOpStart = 0;         //0%
       
    44 
       
    45 _LIT(KPddName, "Media.NFE");
       
    46 #define NFE_DRIVENAME "NFE"
       
    47 #define NFE_NUMMEDIA 1
       
    48 
       
    49 // Define the array of local drives which we're attaching to
       
    50 __ASSERT_COMPILE(sizeof(TNfeDeviceInfo) <= 256);	// KMaxQueryDeviceLength
       
    51 
       
    52 // Define the array of local code-paging drives which we're attaching to
       
    53 #ifdef __DEMAND_PAGING__
       
    54 	__ASSERT_COMPILE(NFE_PAGEDRIVECOUNT <= TNfeDeviceInfo::ENfeMaxPartitionEntries);
       
    55 	__ASSERT_COMPILE(NFE_DRIVECOUNT >= NFE_PAGEDRIVECOUNT);
       
    56 	#define	SECTOR_SHIFT 9
       
    57 #endif	// #ifdef __DEMAND_PAGING__
       
    58 
       
    59 
       
    60 
       
    61 
       
    62 class DPrimaryMediaExt : public DPrimaryMediaBase
       
    63 	{
       
    64 public:
       
    65 	DPrimaryMediaExt(TInt aInstance);
       
    66 public:
       
    67 	TInt iInstance;
       
    68 	TDfcQue iNfeDfcQ;
       
    69 	};
       
    70 
       
    71 
       
    72 
       
    73 // Get the number of drives in the drive array belonging to this instance 
       
    74 TInt DriveCount(TInt aInstance)
       
    75 	{
       
    76 	static const TInt NfeInstanceDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_DRIVE_COUNTS};
       
    77 	return NfeInstanceDriveCounts[aInstance];
       
    78 	}
       
    79 
       
    80 // Get a pointer to the first drive in the drive array belonging to this instance 
       
    81 const TInt* DriveList(TInt aInstance)
       
    82 	{
       
    83 	static const TInt NfeDriveNumbers[NFE_DRIVECOUNT]={NFE_DRIVELIST};
       
    84 	TInt driveListOffset = 0;
       
    85 	for (TInt n=0; n<aInstance; n++)
       
    86 		driveListOffset+= DriveCount(n);
       
    87 	return  NfeDriveNumbers + driveListOffset;
       
    88 	}
       
    89 
       
    90 const TInt* DriveLetterList(TInt aInstance)
       
    91 	{
       
    92 	static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
       
    93 	TInt driveListOffset = 0;
       
    94 	for (TInt n=0; n<aInstance; n++)
       
    95 		driveListOffset+= DriveCount(n);
       
    96 	return  NfeDriveLetters + driveListOffset;
       
    97 	}
       
    98 
       
    99 TInt DriveLetter(TInt aIndex)
       
   100 	{
       
   101 	static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
       
   102 	return NfeDriveLetters[aIndex];
       
   103 	}
       
   104 
       
   105 TChar DriveLetterToAscii(TInt aDriveLetter)
       
   106 	{
       
   107 	return aDriveLetter >= 0 && aDriveLetter <= 25 ? aDriveLetter +'A' : '?';
       
   108 	}
       
   109 
       
   110 #ifdef __DEMAND_PAGING__
       
   111 	// Get the number of drives in the paged drive array belonging to this instance 
       
   112 	TInt PageDriveCount(TInt aInstance)
       
   113 		{
       
   114 	#if NFE_PAGEDRIVECOUNT > 0
       
   115 		static const TInt NfeInstancePageDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGEDRIVE_COUNTS};
       
   116 		return NfeInstancePageDriveCounts[aInstance];
       
   117 	#else
       
   118 		return 0;
       
   119 	#endif
       
   120 		}
       
   121 
       
   122 	// Get a pointer to the first drive in the paged drive array belonging to this instance 
       
   123 	const TInt* PageDriveList(TInt aInstance)
       
   124 		{
       
   125 	#if NFE_PAGEDRIVECOUNT > 0
       
   126 		static const TInt NfePageDriveNumbers[NFE_PAGEDRIVECOUNT]={NFE_PAGEDRIVELIST};
       
   127 		TInt driveListOffset = 0;
       
   128 		for (TInt n=0; n<aInstance; n++)
       
   129 			driveListOffset+= PageDriveCount(n);
       
   130 		return  NfePageDriveNumbers + driveListOffset;
       
   131 	#else
       
   132 		return NULL;
       
   133 	#endif
       
   134 		}
       
   135 
       
   136 	// Get the number of paging type belonging to this instance 
       
   137 	TInt PagingType(TInt aInstance)
       
   138 		{
       
   139 	#if NFE_PAGEDRIVECOUNT > 0
       
   140 		static const TInt NfeInstancePagingType[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGING_TYPE};
       
   141 		return NfeInstancePagingType[aInstance];
       
   142 	#else
       
   143 		return 0;
       
   144 	#endif
       
   145 		}
       
   146 
       
   147 	// get the instance of the swap drive
       
   148 	TInt SwapInstance()
       
   149 		{
       
   150 		for (TInt i=0; i<NFE_INSTANCE_COUNT; i++)
       
   151 			if (PagingType(i) & DPagingDevice::EData)
       
   152 				return i;
       
   153 		return KErrNotFound;
       
   154 		}
       
   155 #endif	// #ifdef __DEMAND_PAGING__
       
   156 
       
   157 
       
   158 const char* DriveStatus(TNfeDiskStatus aStatus)
       
   159 	{
       
   160 	const char* KNfeUnmounted = "Unmounted";
       
   161 	const char* KNfeDecrypted = "Decrypted";
       
   162 	const char* KNfeDecrypting = "Decrypting";
       
   163 	const char* KNfeEncrypted = "Encrypted";
       
   164 	const char* KNfeEncrypting = "Encrypting";
       
   165 	const char* KNfeWiping = "Wiping";
       
   166 	const char* KNfeCorrupted = "Corrupted";
       
   167 	const char* KNfeUnrecognised = "Unrecognised";
       
   168 
       
   169 	switch(aStatus)
       
   170 		{
       
   171 		case ENfeUnmounted:
       
   172 			return KNfeUnmounted;
       
   173 		case ENfeDecrypted:
       
   174 			return KNfeDecrypted;
       
   175 		case ENfeDecrypting:
       
   176 			return KNfeDecrypting;
       
   177 		case ENfeEncrypted:
       
   178 			return KNfeEncrypted;
       
   179 		case ENfeEncrypting:
       
   180 			return KNfeEncrypting;
       
   181 		case ENfeWiping:
       
   182 			return KNfeWiping;
       
   183 		case ENfeCorrupted:
       
   184 			return KNfeCorrupted;
       
   185 		default:
       
   186 			return KNfeUnrecognised;
       
   187 
       
   188 		}
       
   189 	}
       
   190 
       
   191 
       
   192 DPrimaryMediaExt::DPrimaryMediaExt(TInt aInstance) : iInstance(aInstance)
       
   193 	{
       
   194 	}
       
   195 
       
   196 
       
   197 #define NFE_FAULT()	Kern::Fault("NFEMEDIA",__LINE__)
       
   198 
       
   199 // disk encryption/decryption/wiping is only performed after the following period of inactivity
       
   200 // NB USB Mass Storage tends to 'poll' the media driver by sending ECaps every second or so, so we need
       
   201 // to ensure this timeout period is significantly less to ensure the timer DFC thread gets a chance to run...
       
   202 const TInt KNotBusyInterval = 200;		// 200 mS
       
   203 
       
   204 
       
   205 
       
   206 class DPhysicalDeviceMediaNFE : public DPhysicalDevice
       
   207 	{
       
   208 public:
       
   209 	DPhysicalDeviceMediaNFE();
       
   210 	virtual TInt Install();
       
   211 	virtual void GetCaps(TDes8& aDes) const;
       
   212 	virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
       
   213 	virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
       
   214 	virtual TInt Info(TInt aFunction, TAny* a1);
       
   215 	};
       
   216 								
       
   217 
       
   218 class DMediaDriverNFE : public DMediaDriverExtension
       
   219 	{
       
   220 public:
       
   221 	class TPropertyObserver
       
   222 		{
       
   223 	public:
       
   224 		void Close();
       
   225 		static void PropertySubsCompleteFn(TAny* aPtr, TInt aReason);
       
   226 	public:
       
   227 		TInt iDriveIndex;
       
   228 		DMediaDriverNFE* iMediaExt;
       
   229 		RPropertyRef iProperty;
       
   230 		TPropertySubsRequest* iPropertySubsRequest;
       
   231 		TDfc* iPropertyDfc;	// N.B. subscription call backs don't occur in our thread context, hence the need for this DFC
       
   232 		TInt iValue;
       
   233 		};
       
   234 
       
   235 public:
       
   236 	 DMediaDriverNFE(TInt aMediaId);
       
   237 	~DMediaDriverNFE();
       
   238 
       
   239 	// replacing pure virtual
       
   240 	virtual TInt Request(TLocDrvRequest& aRequest);
       
   241 	virtual TInt PartitionInfo(TPartitionInfo &anInfo);
       
   242 
       
   243 	TInt DoCreate(TInt aMediaId);
       
   244 	void Close();
       
   245 
       
   246 	TNfeDriveInfo*  GetSwapDrive();
       
   247 
       
   248 private:
       
   249 	TInt HandleRead(TLocDrvRequest& aRequest);
       
   250 	TInt HandleWrite(TLocDrvRequest& aRequest);
       
   251 	TInt HandleFormat(TLocDrvRequest& aRequest);
       
   252 	TInt HandleCaps(TLocDrvRequest& aReq);
       
   253 
       
   254 
       
   255 	void EncryptBuffer(TDes8& aBuffer);
       
   256 	void DecryptBuffer(TDes8& aBuffer);
       
   257 
       
   258 	inline TUint8 EncryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
       
   259 	inline TUint8 DecryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
       
   260 	inline TInt DriveIndex(TInt aDriveNum) {return iDriveNumToIndex[aDriveNum];}
       
   261 
       
   262 	static void IdleTimerCallBack(TAny* aMediaDriver);
       
   263 	static void TimerDfcFunction(TAny* aMediaDriver);
       
   264 
       
   265 	// Publish & Subscribe stuff - used to listen to requests from UI 
       
   266 	static void FromUiPropertyDfcFunction(TAny* aObserver);
       
   267 	void FromUiPropertyDfc(TPropertyObserver& aObserver);
       
   268 
       
   269 	// Publish & Subscribe stuff - used to listen to status setting from other NFE drives
       
   270 	static void StatusToUiPropertyDfcFunction(TAny* aObserver);
       
   271 	void StatusToUiPropertyDfc(TPropertyObserver& aObserver);
       
   272 
       
   273 	void StartEncrypting();
       
   274 	void StartDecrypting();
       
   275 
       
   276 	TInt HandleDiskContent();	// called from idle timer DFC
       
   277 
       
   278 	TNfeDriveInfo* NextDrive();
       
   279 	
       
   280 	TBool AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen);
       
   281 
       
   282 	void SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus);
       
   283 
       
   284 	TBool ValidBootSector(TUint8* aBuffer);
       
   285 	TUint32 VolumeId(TUint8* aBuffer);
       
   286 	void CheckBootSector(TNfeDriveInfo &aDriveInfo);
       
   287 	TInt WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised = EFalse);
       
   288 
       
   289 private:
       
   290 	TInt iInstance;		// media drive instance
       
   291 
       
   292 	// A local buffer use for encryting / decrypting
       
   293 	// For paging requests we need this to be page aligned, so allocate enough to cater for 
       
   294 	// the worst case of up to 4K being wasted at the start of the buffer and the end
       
   295 	enum {KSectorSize = 512, KPageSize = 4096, KBufSize = 65536};
       
   296 	TUint8 iNonPageAlignedBuffer[KBufSize + KPageSize*2];
       
   297 	// a pointer to the start of the first page in iNonPageAlignedBuffer
       
   298 	TUint8* iBuffer;
       
   299 
       
   300 	
       
   301 	// Idle timer & DFC for kicking an encryption pass
       
   302 	NTimer iIdleTimer;
       
   303 	TDfc iTimerDfc;
       
   304 
       
   305 	TInt iDriveIndex;								// index of local drive number currently being encrypted
       
   306 	TInt iDriveNumToIndex[KMaxPartitionEntries];	// maps drive numbers to index
       
   307 
       
   308 	TBool iBusy;
       
   309 
       
   310 	const TInt* iDriveList;	// pointer into the drives in NFE_DRIVELIST belonging to this media driver
       
   311 	const TInt* iDriveLetterList;	// pointer into the drive letter in NFE_DRIVELETTERLIST belonging to this media driver
       
   312 
       
   313 	// Publish & subscribe stuff which handles drive command notification events from the UI
       
   314 	TPropertyObserver iFromUiPropertyObserver[NFE_DRIVECOUNT];
       
   315 
       
   316 	// Publish & subscribe stuff which handles drive status notification events from the other NFE drives
       
   317 	TPropertyObserver iStatusToUiPropertyObserver[NFE_DRIVECOUNT];
       
   318 
       
   319 	TBool iDriveFinalised;
       
   320 
       
   321 public:
       
   322 	// Partition information etc for drives this driver is attached to
       
   323 	TNfeDeviceInfo iInfo;
       
   324 	};
       
   325 
       
   326 
       
   327 
       
   328 class TBootSectorStatus
       
   329 	{
       
   330 public:
       
   331 	TUint8 iFatBootSectorData[128];
       
   332 	
       
   333 	enum {ENfeBootSectorSignature = 0x2045464E};	// 'NFE '
       
   334 	TUint32 iSignature;
       
   335 
       
   336 	TNfeDiskStatus iStatus;
       
   337 	TBool iFinalised;
       
   338 	TInt64 iEncryptEndPos;	// position of the last encrypted byte +1. Only written when device is powered down
       
   339 	};
       
   340 
       
   341 
       
   342 DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()
       
   343 	{
       
   344 	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()"));
       
   345 	iUnitsMask=0x1;
       
   346 	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
       
   347 	}
       
   348 
       
   349 /**
       
   350 Install the Internal NFE PDD.
       
   351 */
       
   352 TInt DPhysicalDeviceMediaNFE::Install()
       
   353 	{
       
   354 	__KTRACE_PRINT(Kern::Printf(": TInt DPhysicalDeviceMediaNFE::Install()"));
       
   355 
       
   356 	return SetName(&KPddName);
       
   357 	}
       
   358 
       
   359 void DPhysicalDeviceMediaNFE::GetCaps(TDes8& /*aDes*/) const
       
   360 	{
       
   361 	}
       
   362 
       
   363 /**
       
   364 Create an NFE media driver.
       
   365 */
       
   366 TInt DPhysicalDeviceMediaNFE::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
       
   367 	{
       
   368 	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Create()"));
       
   369 
       
   370 	if (!Kern::QueryVersionSupported(iVersion,aVer))
       
   371 		return KErrNotSupported;
       
   372 
       
   373 	TInt r=KErrNoMemory;
       
   374 
       
   375 	DMediaDriverNFE* pD = new DMediaDriverNFE(aMediaId);
       
   376 	aChannel=pD;
       
   377 	if (pD)
       
   378 		r=pD->DoCreate(aMediaId);
       
   379 
       
   380 	if (r == KErrNone)
       
   381 		pD->OpenMediaDriverComplete(KErrNone);
       
   382 
       
   383 	return r;
       
   384 	}
       
   385 
       
   386 TInt DPhysicalDeviceMediaNFE::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
       
   387 	{
       
   388 	TInt r;
       
   389 	if (!Kern::QueryVersionSupported(iVersion,aVer))
       
   390 		r = KErrNotSupported;
       
   391 	else if (aDeviceType == MEDIA_DEVICE_NFE)
       
   392 		return r = KErrNone;
       
   393 	else
       
   394 		r = KErrNotSupported;
       
   395 
       
   396 //	__KTRACE_PRINT(Kern::Printf("DPhysicalDeviceMediaNFE::Validate() aDeviceType %d NfeDeviceType %d r %d", aDeviceType, MEDIA_DEVICE_NFE, r));
       
   397 	return r;
       
   398 	}
       
   399 
       
   400 TInt DPhysicalDeviceMediaNFE::Info(TInt aFunction, TAny*)
       
   401 //
       
   402 // Return the priority of this media driver
       
   403 //
       
   404 	{
       
   405 //	__KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Info()"));
       
   406 
       
   407 	if (aFunction==EPriority)
       
   408 		return KMediaDriverPriorityNormal;
       
   409 
       
   410 	if (aFunction==EMediaDriverPersistent)
       
   411 		return KErrNone;
       
   412 
       
   413 	return KErrNotSupported;
       
   414 	}
       
   415 
       
   416 DMediaDriverNFE::DMediaDriverNFE(TInt aMediaId) :
       
   417 	DMediaDriverExtension(aMediaId),
       
   418 	iInstance(((DPrimaryMediaExt*) iPrimaryMedia)->iInstance),
       
   419 	iIdleTimer(IdleTimerCallBack,this),
       
   420 	iTimerDfc(TimerDfcFunction,this,2),
       
   421 	iDriveList (DriveList(iInstance)),
       
   422 	iDriveLetterList (DriveLetterList(iInstance))
       
   423 	{
       
   424 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DMediaDriverNFE()", iInstance));
       
   425 	iInfo.iDriveCount = DriveCount(iInstance);
       
   426 
       
   427 	__ASSERT_ALWAYS(Kern::RoundToPageSize(1) == KPageSize, NFE_FAULT());
       
   428 
       
   429 	// Align the buffer to a page boundary to improve efficiency for paging requests
       
   430 	iBuffer = &iNonPageAlignedBuffer[0];
       
   431 	iBuffer = (TUint8*) ((((TUint32) &iNonPageAlignedBuffer[0]) + KPageSize-1) & ~(KPageSize-1));
       
   432 	}
       
   433 
       
   434 DMediaDriverNFE::~DMediaDriverNFE()
       
   435 //
       
   436 // Destructor.
       
   437 //
       
   438 	{
       
   439 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::~DMediaDriverNFE()", iInstance));
       
   440 
       
   441 	TInt i;
       
   442 	for (i=0; i<TNfeDeviceInfo::ENfeMaxPartitionEntries; i++)
       
   443 		{
       
   444 		RPropertyRef* property = (RPropertyRef*) iInfo.iDrives[i].iStatusToUiProperty;
       
   445 		if (property)
       
   446 			{
       
   447 			property->Delete();
       
   448 			delete property;
       
   449 			}
       
   450 		property = (RPropertyRef*) iInfo.iDrives[i].iToUiProperty;
       
   451 		if (property)
       
   452 			{
       
   453 			property->Delete();
       
   454 			delete property;
       
   455 			}
       
   456 		property = (RPropertyRef*) iInfo.iDrives[i].iProgressToUiProperty;
       
   457 		if (property)
       
   458 			{
       
   459 			property->Delete();
       
   460 			delete property;
       
   461 			}
       
   462 		}
       
   463 
       
   464 	for (i=0; i<NFE_DRIVECOUNT; i++)
       
   465 		{
       
   466 		iFromUiPropertyObserver[i].Close();
       
   467 		iStatusToUiPropertyObserver[i].Close();
       
   468 		}
       
   469 	}
       
   470 
       
   471 
       
   472 TInt CreateKey(RPropertyRef*& aProperty, TUint aKey)
       
   473 	{
       
   474 	aProperty = new RPropertyRef;
       
   475 	if (aProperty == NULL)
       
   476 		return KErrNoMemory;
       
   477 	TInt r = aProperty->Attach(KNfeUID, aKey);
       
   478 	if (r != KErrNone)
       
   479 		return r;
       
   480 
       
   481     static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
       
   482 	r = aProperty->Define( RProperty::EInt, KPassPolicy, KPassPolicy );
       
   483 	if (r != KErrNone && r != KErrAlreadyExists)
       
   484 		return r;
       
   485 	return KErrNone;
       
   486 	}
       
   487 
       
   488 TInt DMediaDriverNFE::DoCreate(TInt /*aMediaId*/)
       
   489 //
       
   490 // Create the media driver.
       
   491 //
       
   492 	{
       
   493 	__KTRACE_PRINT(Kern::Printf("NFE%d: TInt DMediaDriverNFE::DoCreate()", iInstance));
       
   494 
       
   495 	// Associate the idle timer DFC with our thread
       
   496 	iTimerDfc.SetDfcQ(iPrimaryMedia->iDfcQ);
       
   497 
       
   498 	// Publish & Subscribe stuff - used to initiate an encryption pass from the test app
       
   499 	static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
       
   500 	TInt r;
       
   501 	TInt i;
       
   502 
       
   503 	TInt swapInstance = KErrNotFound;
       
   504 #if defined (__DEMAND_PAGING__)
       
   505 	swapInstance = SwapInstance();
       
   506 #endif
       
   507 
       
   508 	// **************************************************************************************
       
   509 	// Set up P&S publishers so we can publish the status for our drives
       
   510 	// **************************************************************************************
       
   511 	__KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi, ToUi, ProgressToUi P&S publisher & FromUi P&S observer", iInstance));
       
   512 
       
   513 	for (i = 0; i<DriveCount(iInstance); i++)
       
   514 		{
       
   515 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
       
   516 		TInt driveLetter = iDriveLetterList[i];
       
   517 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(driveLetter)));
       
   518 
       
   519 		// no point setting up P&S for the swap drive
       
   520 		if (driveLetter == -1)
       
   521 			{
       
   522 			__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping P&S for swap partition", iInstance, i));
       
   523 			continue;
       
   524 			}
       
   525 
       
   526 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iStatusToUiProperty, NFE_KEY(driveLetter, KNfeStatusToUiKey));
       
   527 		if (r != KErrNone)
       
   528 			return r;
       
   529 
       
   530 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iToUiProperty, NFE_KEY(driveLetter, KNfeToUiKey));
       
   531 		if (r != KErrNone)
       
   532 			return r;
       
   533 
       
   534 		r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iProgressToUiProperty, NFE_KEY(driveLetter, KNfeProgressToUiKey));
       
   535 		if (r != KErrNone)
       
   536 			return r;
       
   537 
       
   538 		TPropertyObserver& observer = iFromUiPropertyObserver[i];
       
   539 		observer.iDriveIndex = i;
       
   540 		observer.iMediaExt = this;
       
   541 		observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
       
   542 		if (observer.iPropertySubsRequest == NULL)
       
   543 			return KErrNoMemory;
       
   544 
       
   545 		observer.iPropertyDfc = new TDfc(FromUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
       
   546 		if (observer.iPropertyDfc == NULL)
       
   547 			return KErrNoMemory;
       
   548 		
       
   549 		r = observer.iProperty.Attach(KNfeUID, NFE_KEY(driveLetter, KNfeToThreadKey));
       
   550 		if (r != KErrNone)
       
   551 			return r;
       
   552 		r = observer.iProperty.Define(
       
   553 			RProperty::EInt,
       
   554 			KPassPolicy, 
       
   555 			KPassPolicy);
       
   556 		if (r != KErrNone && r != KErrAlreadyExists)
       
   557 			return r;
       
   558 
       
   559 		r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
       
   560 		if (r != KErrNone)
       
   561 			return r;
       
   562 		}
       
   563 
       
   564 	// **************************************************************************************
       
   565 	// If this instance owns the swap partition,
       
   566 	// set up P&S listeners so we can get status notification events from the other drives
       
   567 	// **************************************************************************************
       
   568 	__KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi P&S observer", iInstance));
       
   569 
       
   570 	for (i = 0; i < (iInstance == swapInstance ? NFE_DRIVECOUNT : -1); i++)
       
   571 		{
       
   572 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
       
   573 		__KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(DriveLetter(i))));
       
   574 
       
   575 		// no point setting up P&S for the swap drive
       
   576 		if (DriveLetter(i) == -1)
       
   577 			{
       
   578 			__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping StatusToUi P&S observer for swap partition", iInstance, i));
       
   579 			continue;
       
   580 			}
       
   581 
       
   582 		__KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Setting up StatusToUi P&S observer for drive %c", iInstance, i, (TInt) DriveLetterToAscii(DriveLetter(i))));
       
   583 		TPropertyObserver& observer = iStatusToUiPropertyObserver[i];
       
   584 		observer.iDriveIndex = i;
       
   585 		observer.iMediaExt = this;
       
   586 		observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
       
   587 		if (observer.iPropertySubsRequest == NULL)
       
   588 			return KErrNoMemory;
       
   589 
       
   590 		observer.iPropertyDfc = new TDfc(StatusToUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
       
   591 		if (observer.iPropertyDfc == NULL)
       
   592 			return KErrNoMemory;
       
   593 		
       
   594 		r = observer.iProperty.Attach(KNfeUID, NFE_KEY(DriveLetter(i), KNfeStatusToUiKey));
       
   595 		if (r != KErrNone)
       
   596 			return r;
       
   597 		r = observer.iProperty.Define(
       
   598 			RProperty::EInt,
       
   599 			KPassPolicy, 
       
   600 			KPassPolicy);
       
   601 		if (r != KErrNone && r != KErrAlreadyExists)
       
   602 			return r;
       
   603 
       
   604 		r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
       
   605 		if (r != KErrNone)
       
   606 			return r;
       
   607 		}
       
   608 
       
   609 	return(KErrNone);
       
   610 	}
       
   611 
       
   612 void DMediaDriverNFE::TPropertyObserver::Close()
       
   613 	{
       
   614 	iProperty.Close();
       
   615 	delete iPropertyDfc;
       
   616 	iPropertyDfc = NULL;
       
   617 	delete iPropertySubsRequest;
       
   618 	iPropertySubsRequest = NULL;
       
   619 	}
       
   620 
       
   621 void DMediaDriverNFE::TPropertyObserver::PropertySubsCompleteFn(TAny* aPtr, TInt /*aReason*/)
       
   622 	{
       
   623 	TPropertyObserver* self = (TPropertyObserver*) aPtr;
       
   624 	// Queue a DFC to ensure we're running in the correct thread
       
   625 	self->iPropertyDfc->Enque();
       
   626 	}
       
   627 
       
   628 void DMediaDriverNFE::FromUiPropertyDfcFunction(TAny* aObserver)
       
   629 	{
       
   630 	TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
       
   631 	observer.iMediaExt->FromUiPropertyDfc(observer);
       
   632 	}
       
   633 
       
   634 void DMediaDriverNFE::FromUiPropertyDfc(TPropertyObserver& aObserver)
       
   635 	{
       
   636     // Get the value of request from the UI
       
   637     TInt err = aObserver.iProperty.Get(aObserver.iValue);
       
   638 
       
   639 	TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
       
   640 	__ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
       
   641 
       
   642 	TInt driveLetter = iDriveLetterList[aObserver.iDriveIndex];
       
   643 
       
   644 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::FromUiPropertyDfc() cmd %d driveLetter %c", 
       
   645 		iInstance, aObserver.iValue, (TInt) DriveLetterToAscii(driveLetter)));
       
   646 
       
   647 	// is this our drive letter ?
       
   648 	TInt driveCount = DriveCount(iInstance);
       
   649 	TNfeDriveInfo* driveInfo = NULL;
       
   650 
       
   651 	for (TInt i=0; i<driveCount; i++)
       
   652 		{
       
   653 		TInt myDriveLetter = iDriveLetterList[i];
       
   654 
       
   655 		__KTRACE_PRINT(Kern::Printf("NFE%d: Comparing drive %c with myDrive %c", iInstance, (TInt) DriveLetterToAscii(driveLetter), (TInt) DriveLetterToAscii(myDriveLetter)));
       
   656 
       
   657 		if (myDriveLetter == driveLetter)
       
   658 			{
       
   659 			TInt driveNumber = iDriveList[i];
       
   660 			driveInfo = &iInfo.iDrives[iDriveNumToIndex[driveNumber]];
       
   661 			__KTRACE_PRINT(Kern::Printf("NFE%d: Drive Match found driveNumber %d", iInstance, driveInfo->iLocalDriveNum));
       
   662 
       
   663 			__ASSERT_ALWAYS(driveInfo->iProgressToUiProperty, NFE_FAULT());
       
   664 			((RPropertyRef*) (driveInfo->iProgressToUiProperty))->Set(0); 
       
   665 			// Wake up the possibly waiting client, whether or not the request
       
   666 			// was successfull.
       
   667 			((RPropertyRef*) (driveInfo->iToUiProperty))->Set( err ); // Return value ignored
       
   668 			break;
       
   669 			}
       
   670 		}
       
   671 
       
   672 
       
   673 	__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));
       
   674 
       
   675 	if (err == KErrNone && aObserver.iValue == ENfeEncryptDisk && driveInfo != NULL)
       
   676 		{
       
   677 		if (driveInfo->Status() == ENfeDecrypted)
       
   678 			{
       
   679 			SetStatus(*driveInfo, ENfeEncrypting);
       
   680 			StartEncrypting();
       
   681 			}
       
   682 		}
       
   683 	if (err == KErrNone && aObserver.iValue == ENfeDecryptDisk && driveInfo != NULL)
       
   684 		{
       
   685 		if (driveInfo->Status() == ENfeEncrypted)
       
   686 			{
       
   687 			SetStatus(*driveInfo, ENfeDecrypting);
       
   688 			StartDecrypting();
       
   689 			}
       
   690 		}
       
   691 	}
       
   692 
       
   693 
       
   694 void DMediaDriverNFE::StatusToUiPropertyDfcFunction(TAny* aObserver)
       
   695 	{
       
   696 	TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
       
   697 	observer.iMediaExt->StatusToUiPropertyDfc(observer);
       
   698 	}
       
   699 
       
   700 void DMediaDriverNFE::StatusToUiPropertyDfc(TPropertyObserver& aObserver)
       
   701 	{
       
   702     // Get the value of request from the UI
       
   703     TInt err = aObserver.iProperty.Get(aObserver.iValue);
       
   704 
       
   705 	TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
       
   706 	__ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
       
   707 
       
   708 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::StatusToUiPropertyDfc() status %d driveLetter %c", 
       
   709 		iInstance, aObserver.iValue, DriveLetter(aObserver.iDriveIndex) >=0 ? DriveLetter(aObserver.iDriveIndex)+'A' : '?'));
       
   710 
       
   711 
       
   712 	__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));
       
   713 
       
   714 	if (err == KErrNone && (aObserver.iValue == ENfeEncrypted || aObserver.iValue == ENfeEncrypting))
       
   715 		{
       
   716 		// If any drive is being or is already encrypted then we have to encrypt the swap partition...
       
   717 		TNfeDriveInfo* diSwap = GetSwapDrive();
       
   718 		if (diSwap != NULL && diSwap->Status() == ENfeDecrypted)
       
   719 			{
       
   720 			SetStatus(*diSwap, ENfeEncrypting);
       
   721 			StartEncrypting();
       
   722 			}
       
   723 		}
       
   724 	}
       
   725 
       
   726 
       
   727 void DMediaDriverNFE::Close()
       
   728 	{
       
   729 	__KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::Close()", iInstance));
       
   730 	DMediaDriverExtension::Close();
       
   731 	}
       
   732 
       
   733 
       
   734 void DMediaDriverNFE::SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus)
       
   735 	{
       
   736 	if (aStatus != aDi.Status())
       
   737 		{
       
   738 		aDi.SetStatus(aStatus);
       
   739 		__KTRACE_PRINT(Kern::Printf("NFE%d: SetStatus = %s", iInstance, DriveStatus(aDi.Status())));
       
   740 		}
       
   741 	}
       
   742 
       
   743 void TNfeDriveInfo::SetStatus(TNfeDiskStatus aStatus)
       
   744     {
       
   745 	iStatus = aStatus;
       
   746 	if (IsUDADrive())
       
   747 		{
       
   748 		// Update the status pub&sub variable for UI
       
   749 		__ASSERT_ALWAYS(iStatusToUiProperty, NFE_FAULT());
       
   750 		((RPropertyRef*) iStatusToUiProperty)->Set(aStatus);
       
   751 		}
       
   752 	}
       
   753 
       
   754 
       
   755 
       
   756 
       
   757 TInt DMediaDriverNFE::Request(TLocDrvRequest& aReq)
       
   758 	{
       
   759 //	__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()));
       
   760 
       
   761 	TInt r = KErrNotSupported;
       
   762 
       
   763 	TInt reqId = aReq.Id();
       
   764     TNfeDriveInfo& di = iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
   765 
       
   766 	switch (reqId)
       
   767 		{
       
   768 #if defined(__DEMAND_PAGING__)
       
   769 		case DMediaPagingDevice::ERomPageInRequest:
       
   770 			BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
       
   771 			r=HandleRead(aReq);
       
   772 			break;
       
   773 
       
   774 		case DMediaPagingDevice::ECodePageInRequest:
       
   775 			BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
       
   776 			r=HandleRead(aReq);
       
   777 			break;
       
   778 
       
   779 #endif	// __DEMAND_PAGING__
       
   780 
       
   781 		case DLocalDrive::ERead:
       
   782 			r=HandleRead(aReq);
       
   783 			break;
       
   784 
       
   785 		case DLocalDrive::EWrite:
       
   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 	aDi.iDriveFinalised = aFinalised;
       
  1475 
       
  1476 	TNfeDiskStatus status = aDi.Status();
       
  1477 
       
  1478 	TInt64 currentPos = aDi.iEntry.iPartitionBaseAddr;
       
  1479 	TInt64 currentLen = KSectorSize;
       
  1480 	TNfeDriveInfo* di = &aDi;
       
  1481 	TBool encodeBuffer = EFalse;
       
  1482 
       
  1483 	if (status == ENfeEncrypting || status == ENfeEncrypted || status == ENfeDecrypting)
       
  1484 		encodeBuffer = AdjustRequest(di, currentPos, currentLen);
       
  1485 
       
  1486 
       
  1487 	TInt r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1488 	if (r != KErrNone)
       
  1489 		return r;
       
  1490 	TPtr8 des(iBuffer, I64LOW(currentLen), I64LOW(currentLen));
       
  1491 
       
  1492 	if (encodeBuffer)
       
  1493 		DecryptBuffer(des);
       
  1494 
       
  1495 
       
  1496 	TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1497 
       
  1498 	if (status == ENfeEncrypting || status == ENfeDecrypting)
       
  1499 		{
       
  1500 		bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
       
  1501 		bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
       
  1502 		bootSectorStatus->iStatus = status;
       
  1503 		bootSectorStatus->iFinalised = aFinalised;
       
  1504 		}
       
  1505 	else
       
  1506 		{
       
  1507 		bootSectorStatus->iSignature = 0;
       
  1508 		bootSectorStatus->iEncryptEndPos = 0;
       
  1509 		bootSectorStatus->iStatus = ENfeUnmounted;
       
  1510 		bootSectorStatus->iFinalised = EFalse;
       
  1511 		}
       
  1512 
       
  1513 	if (encodeBuffer)
       
  1514 		EncryptBuffer(des);
       
  1515 
       
  1516 
       
  1517 	r = Write(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1518 	return r;
       
  1519 	}
       
  1520 
       
  1521 
       
  1522 /**
       
  1523 HandleDiskContent - 
       
  1524 
       
  1525 Called from Idle timer DFC
       
  1526 
       
  1527 Starts encrypting the current drive (iDrives[iDriveIndex]) from the current encryption position (iEncryptEndPos)
       
  1528 */
       
  1529 TInt DMediaDriverNFE::HandleDiskContent()
       
  1530 	{
       
  1531 	TNfeDriveInfo* di = &iInfo.iDrives[iDriveIndex];
       
  1532 
       
  1533 	__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d at pos %lx", iInstance, di->iLocalDriveNum, di->iEncryptEndPos));
       
  1534 
       
  1535 	if (di->iDriveFinalised)
       
  1536 		{
       
  1537 	    __KTRACE_PRINT(Kern::Printf("HandleDiskContent aborting as drive has been finalised", iInstance));
       
  1538 		return KErrNone;
       
  1539 		}
       
  1540 
       
  1541 //	TInt KBackgroundPriority = 7;						//*test*
       
  1542 //	Kern::SetThreadPriority(KBackgroundPriority);		//*test*
       
  1543 
       
  1544 	TInt r = KErrNone;
       
  1545 	for (;;)
       
  1546 		{
       
  1547 		// If we've finished encryting this drive, change the state and move on to the next drive
       
  1548 		if (r != KErrNone || di->iEncryptEndPos >= di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen)
       
  1549 			{
       
  1550 			if (di->Status() == ENfeEncrypting)
       
  1551 				{
       
  1552 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1553 				SetStatus(*di,  r == KErrNone ? ENfeEncrypted : ENfeCorrupted);
       
  1554 				}
       
  1555 			if (di->Status() == ENfeDecrypting)
       
  1556 				{
       
  1557 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished decrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1558 				SetStatus(*di,  r == KErrNone ? ENfeDecrypted : ENfeCorrupted);
       
  1559 				}
       
  1560 			
       
  1561 			// write to boot sector to indicate we have finished encrypting/decrypting this drive
       
  1562 			r = WriteEncryptionStatusToBootSector(*di);
       
  1563 
       
  1564 			di = NextDrive();
       
  1565 			if (di == NULL)
       
  1566 				{
       
  1567 				r = KErrCompletion;
       
  1568 				break;
       
  1569 				}
       
  1570 			__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1571 			}
       
  1572 
       
  1573 		// If this media or any of the attached media are busy, stop encrypting & wait for the next idle timeout
       
  1574 		if (MediaBusy(di->iLocalDriveNum))
       
  1575 			{
       
  1576 			__KTRACE_PRINT(Kern::Printf("NFE%d: Media is busy !!!", iInstance));
       
  1577 			r = KErrNone;	// goto sleep & wait for another timer event
       
  1578 			break;
       
  1579 			}
       
  1580 
       
  1581 		TInt64& pos = di->iEncryptEndPos;
       
  1582 		TInt64 partitionEnd = di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen;
       
  1583 		TInt len = (TInt) Min (partitionEnd - pos, KBufSize);
       
  1584 
       
  1585 #if defined(TRACE_ENABLED)
       
  1586 		// print position every 1/16 of the partition size
       
  1587 		TInt64 printPos = Max((di->iEntry.iPartitionLen >> 4) & ~(KBufSize-1), KBufSize);
       
  1588 		if (((di->iEncryptEndPos - di->iEncryptStartPos)% printPos) == 0) 
       
  1589 			__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1590 #endif
       
  1591 //		__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1592 
       
  1593 
       
  1594 		// Read a buffer, encrypt it, and then write it back
       
  1595 		// retry in case of media change
       
  1596 		const TInt KRetries = 5;
       
  1597 		r = KErrNotReady;
       
  1598 		for (TInt i=0; r == KErrNotReady && i < KRetries; i++)
       
  1599 			{
       
  1600 			r = Read(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1601 			if (r != KErrNone)
       
  1602 				continue;
       
  1603 
       
  1604 			TPtr8 des(iBuffer,len,len);
       
  1605 			if (di->Status() == ENfeEncrypting)
       
  1606 				EncryptBuffer(des);
       
  1607 			else
       
  1608 				DecryptBuffer(des);
       
  1609 			
       
  1610 			r = Write(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1611 			}
       
  1612 
       
  1613 		if (r == KErrNone)
       
  1614 			pos+= len;
       
  1615 
       
  1616 		if (di->iProgressToUiProperty)	// no iProgressToUiProperty for swap drive
       
  1617 			{
       
  1618 			TInt progress = (TInt) (KNfeDiskOpReady * (pos - di->iEntry.iPartitionBaseAddr) / di->iEntry.iPartitionLen);
       
  1619 //			__KTRACE_PRINT(Kern::Printf("NFE%d: Progess %d ", progress));
       
  1620 			((RPropertyRef*) (di->iProgressToUiProperty))->Set( progress ); // Return value ignored
       
  1621 			}
       
  1622 		}
       
  1623 	
       
  1624 	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleDiskContent returned %d", iInstance, r));
       
  1625 
       
  1626 	// If not completed, start the idle timer & try again later
       
  1627 	if (r != KErrCompletion)
       
  1628 		iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1629 
       
  1630 //	Kern::SetThreadPriority(KNfeThreadPriority);	//*test*
       
  1631 	
       
  1632 	return r;
       
  1633 	}
       
  1634 
       
  1635 
       
  1636 
       
  1637 DECLARE_EXTENSION_PDD()
       
  1638 	{
       
  1639 	__KTRACE_PRINT(Kern::Printf("DECLARE_EXTENSION_PDD()"));
       
  1640 	return new DPhysicalDeviceMediaNFE;
       
  1641 	}
       
  1642 
       
  1643 DECLARE_STANDARD_EXTENSION()
       
  1644 	{
       
  1645 	__KTRACE_PRINT(Kern::Printf("DECLARE_STANDARD_EXTENSION()"));
       
  1646 
       
  1647 
       
  1648 	// Create the media driver factory object and register this with the kernel
       
  1649 	__KTRACE_PRINT(Kern::Printf("Creating NFE PDD"));
       
  1650 	DPhysicalDeviceMediaNFE* device = new DPhysicalDeviceMediaNFE;
       
  1651 	if (device == NULL)
       
  1652 		return KErrNoMemory;
       
  1653 	TInt r = Kern::InstallPhysicalDevice(device);
       
  1654 	__KTRACE_PRINT(Kern::Printf("Installing NFE PDD in extension init - name %s r:%d", NFE_DRIVENAME, r));
       
  1655 	if (r != KErrNone)
       
  1656 		return r;
       
  1657 
       
  1658 	TInt swapInstance = KErrNotFound;
       
  1659 #if defined (__DEMAND_PAGING__)
       
  1660 	swapInstance = SwapInstance();
       
  1661 #endif
       
  1662 
       
  1663 	DPrimaryMediaExt* primaryMedia[NFE_INSTANCE_COUNT];
       
  1664 	TInt instance;
       
  1665 
       
  1666 	for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1667 		{
       
  1668 		// Register this media device & define which drives we want to attach to.
       
  1669 		// These drives must already be registered with the local media subsystem
       
  1670 		// i.e. this media's kernel extension must be defined AFTER any attached
       
  1671 		// media's kernel extension in the appropriate .IBY file
       
  1672 		__KTRACE_PRINT(Kern::Printf("NFE%d: Creating NFE primary media", instance));
       
  1673 		DPrimaryMediaExt* pM = new DPrimaryMediaExt(instance);
       
  1674 		if (pM == NULL)
       
  1675 			return KErrNoMemory;
       
  1676 		primaryMedia[instance] = pM;
       
  1677 
       
  1678 		_LIT(KMediaThreadName,"NfeThread?");
       
  1679 		HBuf* pMediaThreadName = HBuf::New(KMediaThreadName);
       
  1680 		(*pMediaThreadName)[9] = (TUint8) ('0' + (TUint8) instance);
       
  1681 
       
  1682 		TInt r = Kern::DfcQInit(&pM->iNfeDfcQ,KNfeThreadPriority,pMediaThreadName);
       
  1683 		if (r != KErrNone)
       
  1684 			return r;
       
  1685 
       
  1686 #ifdef CPU_AFFINITY_ANY
       
  1687 		NKern::ThreadSetCpuAffinity((NThread*)(pM->iNfeDfcQ.iThread), KCpuAffinityAny);
       
  1688 #endif
       
  1689 		
       
  1690 
       
  1691 		pM->iDfcQ = &pM->iNfeDfcQ;
       
  1692 		pM->iMsgQ.Receive();
       
  1693 
       
  1694 
       
  1695 		const TInt* driveList = DriveList(instance);
       
  1696 		TInt driveCount = DriveCount(instance);
       
  1697 
       
  1698 		TBuf<4> driveName(_L("NFE?"));
       
  1699 		driveName[3] = (TUint8) ('0' + (TUint8) instance);
       
  1700 
       
  1701 		
       
  1702 		r = LocDrv::RegisterMediaDevice(
       
  1703 			MEDIA_DEVICE_NFE, 
       
  1704 			driveCount, driveList,
       
  1705 			pM, NFE_NUMMEDIA, driveName);
       
  1706 		if (r != KErrNone)
       
  1707 			return r;
       
  1708 
       
  1709 
       
  1710 #if defined (__DEMAND_PAGING__)
       
  1711 		if (PagingType(instance))
       
  1712 			{
       
  1713 			// Define which of the drives we have already attached to have code or data paging enabled 
       
  1714 			const TInt* pageDriveList = PageDriveList(instance);
       
  1715 			TInt pageDriveCount = PageDriveCount(instance);
       
  1716 
       
  1717 			r = LocDrv::RegisterPagingDevice(pM,pageDriveList,pageDriveCount,PagingType(instance),SECTOR_SHIFT,NFE_NUM_PAGES);
       
  1718 			__KTRACE_PRINT(Kern::Printf("NFE%d: Installing NFE PagingDevice in extension init - r:%d", pM->iInstance, r));
       
  1719 			// Ignore error if demand paging not supported by kernel
       
  1720 			if (r == KErrNotSupported)
       
  1721 				r = KErrNone;
       
  1722 			if (r != KErrNone)
       
  1723 				return r;
       
  1724 			}
       
  1725 
       
  1726 
       
  1727 #endif	// __NAND_DEMAND_PAGING__
       
  1728 
       
  1729 		/*
       
  1730 		If there is a swap partition we need to make sure all instances have their PartitionInfo() called
       
  1731 		so that we can flag the swap partition as 'encrypted' if there are any encrypted drives at all
       
  1732 		*/
       
  1733 		if (swapInstance != KErrNotFound)
       
  1734 			{
       
  1735 			TBuf8<sizeof(TLocalDriveCapsV6)> capsBuf;
       
  1736 			capsBuf.SetMax();
       
  1737 			capsBuf.FillZ();
       
  1738 			DLocalDrive::Caps(driveList[0], capsBuf);
       
  1739 			}
       
  1740 		}
       
  1741 		
       
  1742 
       
  1743 	// If we encounter an encrypted drive belonging to ANY NFE instance, then assume the swap partition is 
       
  1744 	// encrypted too. We need to do this because the swap partition has no equivalent of the boot sector
       
  1745 	if (swapInstance != KErrNotFound)
       
  1746 		{
       
  1747 		__KTRACE_PRINT(Kern::Printf("NFE: Searching for encrypted drives to determine whether swap partition should be encrypted..."));
       
  1748 		TBool encryptedDriveFound = EFalse;
       
  1749 		TNfeDriveInfo* swapDriveInfo = NULL;
       
  1750 		for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1751 			{
       
  1752 			DPrimaryMediaExt* pM = primaryMedia[instance];
       
  1753 			DMediaDriverNFE* mediaDriver = (DMediaDriverNFE*) pM->iDriver;
       
  1754 			__ASSERT_ALWAYS(mediaDriver, NFE_FAULT());
       
  1755 
       
  1756 			if (swapDriveInfo == NULL)
       
  1757 				swapDriveInfo = mediaDriver->GetSwapDrive();
       
  1758 
       
  1759 			for (TInt i=0; i<mediaDriver->iInfo.iDriveCount; i++)
       
  1760 				{
       
  1761 				TNfeDriveInfo& di = mediaDriver->iInfo.iDrives[i];
       
  1762 				__KTRACE_PRINT(Kern::Printf("NFE%d: Testing drive %d DriveLetter %c status %s", 
       
  1763 					instance, di.iLocalDriveNum, (TInt) DriveLetterToAscii(di.iDriveLetter), DriveStatus(di.Status()) ));
       
  1764 				if (di.Status() == ENfeEncrypted || di.Status() == ENfeEncrypting)
       
  1765 					encryptedDriveFound = ETrue;
       
  1766 				}
       
  1767 			}
       
  1768 		if (swapDriveInfo)
       
  1769 			{
       
  1770 			swapDriveInfo->SetStatus(encryptedDriveFound ? ENfeEncrypted : ENfeDecrypted);
       
  1771 			swapDriveInfo->iEncryptEndPos = swapDriveInfo->iEntry.iPartitionBaseAddr + swapDriveInfo->iEntry.iPartitionLen;
       
  1772 
       
  1773 			__KTRACE_PRINT(Kern::Printf("NFE: Setting swap partition state to %s...", DriveStatus(swapDriveInfo->Status())));
       
  1774 			}
       
  1775 		}
       
  1776 
       
  1777 
       
  1778 	return r;
       
  1779 	}
       
  1780 
       
  1781