kerneltest/e32test/mediaext/d_nfe.cpp
changeset 123 fc55edbf3919
child 126 2b2a51c87b12
equal deleted inserted replaced
122:70ba09fd07a5 123:fc55edbf3919
       
     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 a copy of the TPartitionEntry
       
   877 		di.iEntry = aInfo.iEntry[i];
       
   878 
       
   879 
       
   880 		// save the local drive number
       
   881 		di.iLocalDriveNum = driveNum;
       
   882 		di.iDriveLetter = iDriveLetterList[i];
       
   883 
       
   884 		__KTRACE_PRINT(Kern::Printf("NFE%d: DriveNum %d", iInstance, driveNum));
       
   885 		__KTRACE_PRINT(Kern::Printf("NFE%d: DriveLetter %c", iInstance, (TInt) DriveLetterToAscii(di.iDriveLetter)));
       
   886 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionBaseAddr %lX", iInstance, di.iEntry.iPartitionBaseAddr));
       
   887 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionLen %lx", iInstance, di.iEntry.iPartitionLen));
       
   888 		__KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionType %x", iInstance, di.iEntry.iPartitionType));
       
   889 		
       
   890 
       
   891 		// If the drive was removed, reset it's state
       
   892 		if (di.iEntry.iPartitionType == KPartitionTypeEmpty)
       
   893 			{
       
   894 			__KTRACE_PRINT(Kern::Printf("NFE%d: Empty Partition, setting state to ENfeUnmounted", iInstance));
       
   895 			SetStatus(di, ENfeUnmounted);
       
   896 			}
       
   897 
       
   898 		// Is this an unencrypted FAT partition ?
       
   899 		if (di.IsUDADrive())
       
   900 			{
       
   901 			r = Read(di.iLocalDriveNum, di.iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
   902 			if (r != KErrNone)
       
   903 				return r;
       
   904 			CheckBootSector(di);
       
   905 			}
       
   906 		
       
   907 
       
   908 		__KTRACE_PRINT(Kern::Printf("NFE%d: status = %s", iInstance, DriveStatus(di.Status())));
       
   909 
       
   910 		__KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptStartPos %lX", iInstance, di.iEncryptStartPos));
       
   911 		__KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptEndPos %lX", iInstance, di.iEncryptEndPos));
       
   912 		__KTRACE_PRINT(Kern::Printf("NFE%d: ", iInstance));
       
   913 		}
       
   914 
       
   915 
       
   916 
       
   917 #ifdef COMPOSITE_DRIVES
       
   918 	// Accumulate the sizes of consecutive FAT drives & report the accumulated size back in the first FAT partition
       
   919 	for (i=0; i<aInfo.iPartitionCount; i++)
       
   920 		{
       
   921 		aInfo.iEntry[i] = iInfo.iDrives[i].iEntry;
       
   922 
       
   923 		if (iInfo.iDrives[i].IsUDADrive())
       
   924 			{
       
   925 			aInfo.iEntry[i].iPartitionLen = 0;
       
   926 			for (TInt j=i; j<aInfo.iPartitionCount; j++)
       
   927 				{
       
   928 				if (iInfo.iDrives[j].IsUDADrive())
       
   929 					{
       
   930 					aInfo.iEntry[i].iPartitionLen+= iInfo.iDrives[j].iEntry.iPartitionLen;
       
   931 					}
       
   932 				}
       
   933 			iInfo.iDrives[i].iCompositeSize = aInfo.iEntry[i].iPartitionLen;
       
   934 			i = j;
       
   935 			}
       
   936 		}
       
   937 #endif
       
   938 
       
   939 
       
   940 	SetTotalSizeInBytes(aInfo.iMediaSizeInBytes);
       
   941 
       
   942 
       
   943 	return KErrCompletion;	// synchronous completion
       
   944 	}
       
   945 
       
   946 /**
       
   947 HandleCaps() - 
       
   948 
       
   949 Return the Caps for a particular drive
       
   950 
       
   951 Queries the caps from the attached drive, ORs in appropriate paging flags & returns
       
   952 */
       
   953 TInt DMediaDriverNFE::HandleCaps(TLocDrvRequest& aReq)
       
   954 	{
       
   955 	// Get caps from slave drive
       
   956 	// NB if we didn't want to alter anything then we could just call ForwardRequest(aReq);
       
   957 	TBuf8<sizeof(TLocalDriveCapsV6)> slaveCapsBuf;
       
   958 	TLocalDriveCapsV6& slaveCaps = *(TLocalDriveCapsV6*) slaveCapsBuf.Ptr();
       
   959 	slaveCapsBuf.SetMax();
       
   960 	slaveCapsBuf.FillZ();
       
   961 	TInt r = Caps(aReq.Drive()->iDriveNumber, slaveCapsBuf);
       
   962 	if (r != KErrNone)
       
   963 		return r;
       
   964 
       
   965 #ifdef COMPOSITE_DRIVES
       
   966 	TInt driveNum = aReq.Drive()->iDriveNumber;
       
   967 	TInt driveIndex = DriveIndex(driveNum);
       
   968 	if (iInfo.iDrives[driveIndex].iCompositeSize)
       
   969 		slaveCaps.iSize = iInfo.iDrives[driveIndex].iCompositeSize;
       
   970 #endif
       
   971 
       
   972 	// copy slave caps to returned caps
       
   973 	TLocalDriveCapsV6& caps = *(TLocalDriveCapsV6*)aReq.RemoteDes();		
       
   974 	caps = slaveCaps;
       
   975 
       
   976 	// set the paging flags
       
   977 #ifdef __DEMAND_PAGING__
       
   978 	TLocDrv& drive = *aReq.Drive();
       
   979 	if (drive.iPrimaryMedia->iPagingMedia)
       
   980 		caps.iMediaAtt|=KMediaAttPageable;
       
   981 	if (drive.iPagingDrv)
       
   982 		caps.iDriveAtt|=KDriveAttPageable;
       
   983 #endif // __DEMAND_PAGING__
       
   984 
       
   985 	return KErrCompletion;
       
   986 	}
       
   987 
       
   988 
       
   989 /**
       
   990 AdjustRequest() - 
       
   991 
       
   992 Adjusts position & length if a request crosses these boundaries:
       
   993 - the start of the partition (if RLocalDrive::ELocDrvWholeMedia set)
       
   994 - the current encrytion point (iEncryptEndPos) N.B. this will point to the end of the partition 
       
   995   if the drive is fully encrypted
       
   996 
       
   997 For composite drives, it also adjusts the position, length & drive number as appropriate to cater for 
       
   998 crossing partition boundaries
       
   999 
       
  1000 returns ETrue if buffer needs encrypting/decrypting
       
  1001 */
       
  1002 
       
  1003 TBool DMediaDriverNFE::AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen)
       
  1004 	{
       
  1005 #ifdef COMPOSITE_DRIVES
       
  1006 	while (aCurrentPos >= aDriveInfo->iEntry.iPartitionLen)
       
  1007 		{
       
  1008 		aCurrentPos-= aDriveInfo->iEntry.iPartitionLen;
       
  1009 		aDriveInfo++;
       
  1010 		}
       
  1011 	if (aCurrentPos + aCurrentLen > aDriveInfo->iEntry.iPartitionLen)
       
  1012 		aCurrentLen = aDriveInfo->iEntry.iPartitionLen - aCurrentPos;
       
  1013 #endif
       
  1014 
       
  1015 	// do we need to encrypt/decrypt this buffer ?
       
  1016 	TBool encodeBuffer = EFalse;
       
  1017 	
       
  1018 	if ((aDriveInfo->Status() == ENfeEncrypted) || aDriveInfo->Status() == ENfeEncrypting)
       
  1019 		{
       
  1020 //		__ASSERT_DEBUG(aDriveInfo->iEncryptEndPos <= aDriveInfo->iEntry.iPartitionBaseAddr + aDriveInfo->iEntry.iPartitionLen, NFE_FAULT());
       
  1021 
       
  1022 		if (aCurrentPos < aDriveInfo->iEncryptStartPos)
       
  1023 			{
       
  1024 			aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptStartPos - aCurrentPos);
       
  1025 			encodeBuffer = EFalse;
       
  1026 			}
       
  1027 		else if (aCurrentPos < aDriveInfo->iEncryptEndPos)
       
  1028 			{
       
  1029 			aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptEndPos - aCurrentPos);
       
  1030 			encodeBuffer = ETrue;
       
  1031 			}
       
  1032 		else
       
  1033 			{
       
  1034 			encodeBuffer = EFalse;
       
  1035 			}
       
  1036 		}
       
  1037 
       
  1038 	return encodeBuffer;
       
  1039 	}
       
  1040 
       
  1041 
       
  1042 TInt DMediaDriverNFE::HandleRead(TLocDrvRequest& aReq)
       
  1043 	{
       
  1044 	TInt r = KErrNone;
       
  1045 	TInt64 currentPos = aReq.Pos();
       
  1046 	TInt64 remainingLength = aReq.Length();
       
  1047 	TInt desPos = 0;
       
  1048 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1049 
       
  1050 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleRead pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1051 
       
  1052 
       
  1053 	di->iReadRequestCount++;
       
  1054 
       
  1055 	if (aReq.Flags() & TLocDrvRequest::ECodePaging)
       
  1056 		di->iCodePagingRequesCount++;
       
  1057 	if (aReq.Flags() & TLocDrvRequest::EDataPaging)
       
  1058 		di->iDataPagingReadRequestCount++;
       
  1059 
       
  1060 	
       
  1061 	// just forward the request if the drive is not encrypted
       
  1062 	if (di->Status() == ENfeDecrypted)
       
  1063 		return ForwardRequest(aReq);
       
  1064 
       
  1065 	
       
  1066 	while(remainingLength)
       
  1067 		{
       
  1068 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1069 
       
  1070 		TBool decryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1071 
       
  1072 		// Read from attached drive
       
  1073 #ifdef __DEMAND_PAGING__
       
  1074 		if (DMediaPagingDevice::PagingRequest(aReq))
       
  1075 			r = ReadPaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1076 		else
       
  1077 #endif
       
  1078 		r = Read(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1079 		if(r != KErrNone)
       
  1080 			break;
       
  1081 
       
  1082 		TPtr8 des(iBuffer, I64LOW(currentLength), I64LOW(currentLength));
       
  1083 
       
  1084 		// decrypt buffer
       
  1085 		if (decryptBuffer)
       
  1086 			DecryptBuffer(des);
       
  1087 
       
  1088 		//  write back to user
       
  1089 		r = aReq.WriteRemote(&des, desPos);
       
  1090 		if(r != KErrNone)
       
  1091 			break;
       
  1092 
       
  1093 		remainingLength-= currentLength;
       
  1094 		currentPos+= currentLength;
       
  1095 		desPos+= I64LOW(currentLength);
       
  1096 		}
       
  1097 
       
  1098 	return r == KErrNone ? KErrCompletion : r;
       
  1099 	}
       
  1100 
       
  1101 TInt DMediaDriverNFE::HandleWrite(TLocDrvRequest& aReq)
       
  1102 	{
       
  1103 	TInt r = KErrNone;
       
  1104 	TInt64 currentPos =  aReq.Pos();
       
  1105 	TInt64 remainingLength = aReq.Length();
       
  1106 	TInt desPos = 0;
       
  1107 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1108 
       
  1109 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleWrite pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1110 
       
  1111 
       
  1112 	di->iWriteRequestCount++;
       
  1113 	if (aReq.Flags() & TLocDrvRequest::EDataPaging)
       
  1114 		di->iDataPagingWriteRequestCount++;
       
  1115 	
       
  1116 
       
  1117 	// just forward the request if the drive is not encrypted
       
  1118 	if (di->Status() == ENfeDecrypted)
       
  1119 		return ForwardRequest(aReq);
       
  1120 
       
  1121 	while(remainingLength)
       
  1122 		{
       
  1123 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1124 
       
  1125 		TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1126 
       
  1127 		// read from user
       
  1128 		TPtr8 des(iBuffer,0,I64LOW(currentLength));
       
  1129 		r = aReq.ReadRemote(&des, desPos);
       
  1130 		if(r != KErrNone)
       
  1131 			break;
       
  1132 		
       
  1133 		// get the length of data read from the user in case user's
       
  1134 		// descriptor is shorter than advertised
       
  1135 		currentLength = des.Length();
       
  1136 		if (currentLength == 0)
       
  1137 			break;
       
  1138 
       
  1139 		// writing to sector zero ?
       
  1140 		if (currentPos >= di->iEntry.iPartitionBaseAddr && 
       
  1141 			currentPos < di->iEntry.iPartitionBaseAddr + KSectorSize && 
       
  1142 			di->IsUDADrive())
       
  1143 			{
       
  1144 			__KTRACE_PRINT(Kern::Printf("NFE%d: Write to sector #0 detected", iInstance));
       
  1145 
       
  1146 
       
  1147 			TUint8* bootSector = iBuffer;
       
  1148 			TUint8 bootSectorBuffer[KSectorSize];
       
  1149 			// writing partial sector ?
       
  1150 			if (currentPos > di->iEntry.iPartitionBaseAddr || currentLength < KSectorSize)
       
  1151 				{
       
  1152 				bootSector = bootSectorBuffer;
       
  1153 				r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) bootSector, KSectorSize);
       
  1154 				if(r != KErrNone)
       
  1155 					break;
       
  1156 				TInt64 readLen = KSectorSize;
       
  1157 				TBool encryptBuffer = AdjustRequest(di, di->iEntry.iPartitionBaseAddr, readLen);
       
  1158 				if (encryptBuffer)
       
  1159 					{
       
  1160 					TPtr8 des(bootSectorBuffer,KSectorSize,KSectorSize);
       
  1161 					DecryptBuffer(des);
       
  1162 					}
       
  1163 				TInt sectorOffset = (TInt) (currentPos - di->iEntry.iPartitionBaseAddr);
       
  1164 				TInt64 copyLen = currentLength;
       
  1165 				if (copyLen > KSectorSize-sectorOffset)
       
  1166 					copyLen = KSectorSize-sectorOffset;
       
  1167 				memcpy(bootSectorBuffer+sectorOffset, iBuffer, (TInt) copyLen);
       
  1168 				}
       
  1169 
       
  1170 			if ((di->Status() == ENfeUnmounted || di->Status() == ENfeCorrupted) && 
       
  1171 				ValidBootSector(bootSector))
       
  1172 				{
       
  1173 				__KTRACE_PRINT(Kern::Printf("NFE%d: Setting status to ENfeDecrypted", iInstance ));
       
  1174 				di->SetStatus(ENfeDecrypted);
       
  1175 				}
       
  1176 			di->iUniqueID = VolumeId(bootSector);		// update the Volume ID
       
  1177 			__KTRACE_PRINT(Kern::Printf("NFE%d: Setting Volume ID to %08X", iInstance, di->iUniqueID ));
       
  1178 			TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1179 			if (di->Status() == ENfeEncrypting || di->Status() == ENfeDecrypting)
       
  1180 				{
       
  1181 				__KTRACE_PRINT(Kern::Printf("NFE%d: Adding NFE status record to boot sector", iInstance ));
       
  1182 				bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
       
  1183 				bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
       
  1184 				bootSectorStatus->iStatus = di->Status();
       
  1185 				bootSectorStatus->iFinalised = EFalse;
       
  1186 				}
       
  1187 			}
       
  1188 
       
  1189 		// encrypt the buffer
       
  1190 		if (encryptBuffer)
       
  1191 			EncryptBuffer(des);
       
  1192 
       
  1193 		// write the data to the attached drive
       
  1194 #ifdef __DEMAND_PAGING__
       
  1195 		if (DMediaPagingDevice::PagingRequest(aReq))
       
  1196 			r = WritePaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1197 		else
       
  1198 #endif
       
  1199 		r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1200 		if(r != KErrNone)
       
  1201 			break;
       
  1202 
       
  1203 		remainingLength-= currentLength;
       
  1204 		currentPos+= currentLength;
       
  1205 		desPos+= I64LOW(currentLength);
       
  1206 		}
       
  1207 
       
  1208 	return r == KErrNone ? KErrCompletion : r;
       
  1209 	}
       
  1210 
       
  1211 TInt DMediaDriverNFE::HandleFormat(TLocDrvRequest& aReq)
       
  1212 	{
       
  1213 	TInt r = KErrNone;
       
  1214 	TInt64 currentPos =  aReq.Pos();
       
  1215 	TInt64 remainingLength = aReq.Length();
       
  1216 	TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
       
  1217 
       
  1218 //	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleFormat pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
       
  1219 
       
  1220 
       
  1221 	// just forward the request if the drive is not encrypted
       
  1222 	if (di->Status() == ENfeDecrypted)
       
  1223 		return ForwardRequest(aReq);
       
  1224 
       
  1225 	// otherwise create a buffer containing NULLs, encrypt it and write that to the attached drive
       
  1226 	while(remainingLength && r == KErrNone)
       
  1227 		{
       
  1228 		TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
       
  1229 
       
  1230 		TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
       
  1231 
       
  1232 		memclr(iBuffer, KBufSize);
       
  1233 		TPtr8 des(iBuffer,KBufSize,KBufSize);
       
  1234 
       
  1235 		if (encryptBuffer)
       
  1236 			EncryptBuffer(des);
       
  1237 		
       
  1238 		r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
       
  1239 		if(r != KErrNone)
       
  1240 			break;
       
  1241 
       
  1242 		remainingLength-= currentLength;
       
  1243 		currentPos+= currentLength;
       
  1244 		}
       
  1245 
       
  1246 	return r == KErrNone ? KErrCompletion : r;
       
  1247 	}
       
  1248 
       
  1249 
       
  1250 void DMediaDriverNFE::EncryptBuffer(TDes8& aBuffer)
       
  1251 	{
       
  1252 	TInt len = aBuffer.Length();
       
  1253 	for(TInt i=0; i<len; i++)
       
  1254 		aBuffer[i] = EncryptByte(aBuffer[i]);
       
  1255 	}
       
  1256 
       
  1257 void DMediaDriverNFE::DecryptBuffer(TDes8& aBuffer)
       
  1258 	{
       
  1259 	TInt len = aBuffer.Length();
       
  1260 	for(TInt i=0; i<len; i++)
       
  1261 		aBuffer[i] = DecryptByte(aBuffer[i]);
       
  1262 	}
       
  1263 
       
  1264 
       
  1265 TNfeDriveInfo* DMediaDriverNFE::GetSwapDrive()
       
  1266 	{
       
  1267 	for (TInt i=0; i<iInfo.iDriveCount; i++)
       
  1268 		{
       
  1269 		TNfeDriveInfo& di = iInfo.iDrives[i];
       
  1270 		if (di.iEntry.iPartitionType == KPartitionTypePagedData)
       
  1271 			{
       
  1272 			return &di;
       
  1273 			}
       
  1274 		}
       
  1275 	return NULL;	// swap drive not found
       
  1276 	}
       
  1277 
       
  1278 /**
       
  1279 Get the first/next drive to encrypt 
       
  1280 */
       
  1281 
       
  1282 TNfeDriveInfo* DMediaDriverNFE::NextDrive()
       
  1283 	{
       
  1284 	for (iDriveIndex = 0; iDriveIndex<iInfo.iDriveCount; iDriveIndex++)
       
  1285 		{
       
  1286 		TNfeDriveInfo& di = iInfo.iDrives[iDriveIndex];
       
  1287 		TNfeDiskStatus status = iInfo.iDrives[iDriveIndex].Status();
       
  1288 		if (status == ENfeEncrypting || status == ENfeDecrypting)
       
  1289 			{
       
  1290 			di.iEncryptStartPos = di.iEncryptEndPos = di.iEntry.iPartitionBaseAddr;
       
  1291 
       
  1292 			// write to boot sector to indicate we are encrypting/decrypting this drive
       
  1293 			WriteEncryptionStatusToBootSector(di);
       
  1294 
       
  1295 			return &di;
       
  1296 			}
       
  1297 		}
       
  1298 	__KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting / decrypting", iInstance));
       
  1299 	iBusy = EFalse;
       
  1300 	return NULL;
       
  1301 	}
       
  1302 
       
  1303 
       
  1304 /** 
       
  1305 Finds the first unencrypted drive & kicks off the idle timer - 
       
  1306 when this expires the encryption of the drive will start
       
  1307 */
       
  1308 void DMediaDriverNFE::StartEncrypting()
       
  1309 	{
       
  1310 	// start encrypting if not already doing so
       
  1311 	if (!iBusy)
       
  1312 		{
       
  1313 		iBusy = ETrue;
       
  1314 		TNfeDriveInfo* di = NextDrive();
       
  1315 		if (di)
       
  1316 			{
       
  1317 			__KTRACE_PRINT(Kern::Printf("NFE%d: Start encrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1318 			iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1319 			}
       
  1320 		}
       
  1321 	}
       
  1322 
       
  1323 /** 
       
  1324 Finds the first unencrypted drive & kicks off the idle timer - 
       
  1325 when this expires the encryption of the drive will start
       
  1326 */
       
  1327 void DMediaDriverNFE::StartDecrypting()
       
  1328 	{
       
  1329 	// start encrypting if not already doing so
       
  1330 	if (!iBusy)
       
  1331 		{
       
  1332 		iBusy = ETrue;
       
  1333 		TNfeDriveInfo* di = NextDrive();
       
  1334 		if (di)
       
  1335 			{
       
  1336 			__KTRACE_PRINT(Kern::Printf("NFE%d: Start decrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1337 			iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1338 			}
       
  1339 		}
       
  1340 	}
       
  1341 
       
  1342 /**
       
  1343 Idle timer callback
       
  1344 Kicks off a DFC to ensure we are running in the correct thread
       
  1345 */
       
  1346 void DMediaDriverNFE::IdleTimerCallBack(TAny* aMediaDriver)
       
  1347 	{
       
  1348 	((DMediaDriverNFE*)aMediaDriver)->iTimerDfc.Add();
       
  1349 	}
       
  1350 
       
  1351 /**
       
  1352 Idle timer DFC
       
  1353 */
       
  1354 void DMediaDriverNFE::TimerDfcFunction(TAny* aMediaDriver)
       
  1355 	{
       
  1356 	((DMediaDriverNFE*) aMediaDriver)->HandleDiskContent();
       
  1357 	}
       
  1358 
       
  1359 
       
  1360 TBool DMediaDriverNFE::ValidBootSector(TUint8* aBuffer)
       
  1361 	{
       
  1362 	if (aBuffer[0] == 0xEB || aBuffer[0] == 0xE9)
       
  1363 		return ETrue;
       
  1364 	else
       
  1365 		return EFalse;
       
  1366 	}
       
  1367 
       
  1368 
       
  1369 TUint32 DMediaDriverNFE::VolumeId(TUint8* aBuffer)
       
  1370 	{
       
  1371 	TUint16 rootDirEntries;
       
  1372 	TUint32 uniqueID;   
       
  1373     memcpy(&rootDirEntries,&aBuffer[17], 2);	// 17   TUint16 iRootDirEntries
       
  1374 	TBool fat32 = rootDirEntries == 0;
       
  1375 	TInt pos = fat32 ? 67 : 39;		// get position of VolumeID
       
  1376 	memcpy(&uniqueID,&aBuffer[pos],4);
       
  1377 	return uniqueID;
       
  1378 	}
       
  1379 
       
  1380 void DMediaDriverNFE::CheckBootSector(TNfeDriveInfo &aDi)
       
  1381 	{
       
  1382 	TNfeDiskStatus  fatBootSectorStatus = ENfeDecrypted;
       
  1383 
       
  1384 	// Try to determine whether the FAT boot sector is encypted
       
  1385 	if (ValidBootSector(iBuffer))
       
  1386 		{
       
  1387 		fatBootSectorStatus = ENfeDecrypted;
       
  1388 		__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is decrypted", iInstance));
       
  1389 		}
       
  1390 	else
       
  1391 		{
       
  1392 		TPtr8 des(iBuffer, KSectorSize, KSectorSize);
       
  1393 		DecryptBuffer(des);
       
  1394 		if (ValidBootSector(iBuffer))
       
  1395 			{
       
  1396 			__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is encrypted", iInstance));
       
  1397 			fatBootSectorStatus = ENfeEncrypted;
       
  1398 			}
       
  1399 		else
       
  1400 			{
       
  1401 			__KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is corrupted", iInstance));
       
  1402 			fatBootSectorStatus = ENfeCorrupted;
       
  1403 			}
       
  1404 		}
       
  1405 
       
  1406 	__KTRACE_PRINT(Kern::Printf("NFE%d: fatBootSectorStatus %d", iInstance, fatBootSectorStatus));
       
  1407 
       
  1408 	// Find out whether the volume has changed
       
  1409 	TUint32 uniqueID = VolumeId(iBuffer);   
       
  1410 	TBool volumeChanged = uniqueID != aDi.iUniqueID;
       
  1411 	__KTRACE_PRINT(Kern::Printf("NFE%d: Old Volume ID %08X", iInstance, aDi.iUniqueID));
       
  1412 	__KTRACE_PRINT(Kern::Printf("NFE%d: New Volume ID %08X", iInstance, uniqueID));
       
  1413 	__KTRACE_PRINT(Kern::Printf("NFE%d: volumeChanged %d", iInstance, volumeChanged));
       
  1414 	aDi.iUniqueID = uniqueID;
       
  1415 
       
  1416 
       
  1417 
       
  1418 	TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1419 
       
  1420 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iSignature %08X", iInstance, bootSectorStatus->iSignature));
       
  1421 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iStatus %d", iInstance, bootSectorStatus->iStatus));
       
  1422 	__KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iEncryptEndPos %lx", iInstance, bootSectorStatus->iEncryptEndPos));
       
  1423 
       
  1424 
       
  1425 	/*
       
  1426 	If there IS NFE info in the boot sector, restore the encryption settings - 
       
  1427 	unless the 'finalised' flag is clear which indicates that the media was removed or power was lost
       
  1428 	while encrypting the device...
       
  1429 
       
  1430 	If there is no NFE info in the boot sector and there has been a volume change, then we can decide  
       
  1431 	whether the drive is encrypted/decrypted/corrupt by examining the boot sector
       
  1432 	*/
       
  1433 	if (volumeChanged && 
       
  1434 		fatBootSectorStatus != ENfeCorrupted &&
       
  1435 		bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
       
  1436 		!bootSectorStatus->iFinalised)
       
  1437 		{
       
  1438 		SetStatus(aDi, ENfeCorrupted);
       
  1439 		}
       
  1440 	else if (volumeChanged && 
       
  1441 		fatBootSectorStatus != ENfeCorrupted &&
       
  1442 		bootSectorStatus->iFinalised &&
       
  1443 		bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
       
  1444 		(bootSectorStatus->iStatus == ENfeDecrypting || bootSectorStatus->iStatus == ENfeEncrypting))
       
  1445 		{
       
  1446 		SetStatus(aDi, bootSectorStatus->iStatus);
       
  1447 		aDi.iEncryptEndPos = bootSectorStatus->iEncryptEndPos;
       
  1448 
       
  1449 		// write to boot sector to indicate we are no longer finalised
       
  1450 		WriteEncryptionStatusToBootSector(aDi, EFalse);	
       
  1451 
       
  1452 		iBusy = ETrue;
       
  1453 		}
       
  1454 	else if (volumeChanged || aDi.Status() == ENfeUnmounted)
       
  1455 		{
       
  1456 		SetStatus(aDi, fatBootSectorStatus);
       
  1457 		if (aDi.Status() == ENfeEncrypted)
       
  1458 			{
       
  1459 			aDi.iEncryptStartPos = aDi.iEntry.iPartitionBaseAddr;
       
  1460 			aDi.iEncryptEndPos = aDi.iEntry.iPartitionBaseAddr + aDi.iEntry.iPartitionLen;
       
  1461 			}
       
  1462 		}
       
  1463 	}
       
  1464 
       
  1465 
       
  1466 TInt DMediaDriverNFE::WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised)
       
  1467 	{
       
  1468 	if (!aDi.IsUDADrive())
       
  1469 		return KErrNone;
       
  1470 
       
  1471 	if (aDi.iDriveFinalised == aFinalised)
       
  1472 		return KErrNone;
       
  1473 
       
  1474 	TNfeDiskStatus status = aDi.Status();
       
  1475 
       
  1476 	TInt64 currentPos = aDi.iEntry.iPartitionBaseAddr;
       
  1477 	TInt64 currentLen = KSectorSize;
       
  1478 	TNfeDriveInfo* di = &aDi;
       
  1479 	TBool encodeBuffer = EFalse;
       
  1480 
       
  1481 	if (status == ENfeEncrypting || status == ENfeEncrypted || status == ENfeDecrypting)
       
  1482 		encodeBuffer = AdjustRequest(di, currentPos, currentLen);
       
  1483 
       
  1484 
       
  1485 	TInt r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1486 	if (r != KErrNone)
       
  1487 		return r;
       
  1488 	TPtr8 des(iBuffer, I64LOW(currentLen), I64LOW(currentLen));
       
  1489 
       
  1490 	if (encodeBuffer)
       
  1491 		DecryptBuffer(des);
       
  1492 
       
  1493 
       
  1494 	TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
       
  1495 
       
  1496 	if (status == ENfeEncrypting || status == ENfeDecrypting)
       
  1497 		{
       
  1498 		bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
       
  1499 		bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
       
  1500 		bootSectorStatus->iStatus = status;
       
  1501 		bootSectorStatus->iFinalised = aFinalised;
       
  1502 		}
       
  1503 	else
       
  1504 		{
       
  1505 		bootSectorStatus->iSignature = 0;
       
  1506 		bootSectorStatus->iEncryptEndPos = 0;
       
  1507 		bootSectorStatus->iStatus = ENfeUnmounted;
       
  1508 		bootSectorStatus->iFinalised = EFalse;
       
  1509 		}
       
  1510 
       
  1511 	if (encodeBuffer)
       
  1512 		EncryptBuffer(des);
       
  1513 
       
  1514 
       
  1515 	r = Write(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
       
  1516 	return r;
       
  1517 	}
       
  1518 
       
  1519 
       
  1520 /**
       
  1521 HandleDiskContent - 
       
  1522 
       
  1523 Called from Idle timer DFC
       
  1524 
       
  1525 Starts encrypting the current drive (iDrives[iDriveIndex]) from the current encryption position (iEncryptEndPos)
       
  1526 */
       
  1527 TInt DMediaDriverNFE::HandleDiskContent()
       
  1528 	{
       
  1529 	TNfeDriveInfo* di = &iInfo.iDrives[iDriveIndex];
       
  1530 
       
  1531 	__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d at pos %lx", iInstance, di->iLocalDriveNum, di->iEncryptEndPos));
       
  1532 
       
  1533 	if (di->iDriveFinalised)
       
  1534 		{
       
  1535 	    __KTRACE_PRINT(Kern::Printf("HandleDiskContent aborting as drive has been finalised", iInstance));
       
  1536 		return KErrNone;
       
  1537 		}
       
  1538 
       
  1539 //	TInt KBackgroundPriority = 7;						//*test*
       
  1540 //	Kern::SetThreadPriority(KBackgroundPriority);		//*test*
       
  1541 
       
  1542 	TInt r = KErrNone;
       
  1543 	for (;;)
       
  1544 		{
       
  1545 		// If we've finished encryting this drive, change the state and move on to the next drive
       
  1546 		if (r != KErrNone || di->iEncryptEndPos >= di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen)
       
  1547 			{
       
  1548 			if (di->Status() == ENfeEncrypting)
       
  1549 				{
       
  1550 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1551 				SetStatus(*di,  r == KErrNone ? ENfeEncrypted : ENfeCorrupted);
       
  1552 				}
       
  1553 			if (di->Status() == ENfeDecrypting)
       
  1554 				{
       
  1555 				__KTRACE_PRINT(Kern::Printf("NFE%d: Finished decrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
       
  1556 				SetStatus(*di,  r == KErrNone ? ENfeDecrypted : ENfeCorrupted);
       
  1557 				}
       
  1558 			
       
  1559 			// write to boot sector to indicate we have finished encrypting/decrypting this drive
       
  1560 			r = WriteEncryptionStatusToBootSector(*di);
       
  1561 
       
  1562 			di = NextDrive();
       
  1563 			if (di == NULL)
       
  1564 				{
       
  1565 				r = KErrCompletion;
       
  1566 				break;
       
  1567 				}
       
  1568 			__KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
       
  1569 			}
       
  1570 
       
  1571 		// If this media or any of the attached media are busy, stop encrypting & wait for the next idle timeout
       
  1572 		if (MediaBusy(di->iLocalDriveNum))
       
  1573 			{
       
  1574 			__KTRACE_PRINT(Kern::Printf("NFE%d: Media is busy !!!", iInstance));
       
  1575 			r = KErrNone;	// goto sleep & wait for another timer event
       
  1576 			break;
       
  1577 			}
       
  1578 
       
  1579 		TInt64& pos = di->iEncryptEndPos;
       
  1580 		TInt64 partitionEnd = di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen;
       
  1581 		TInt len = (TInt) Min (partitionEnd - pos, KBufSize);
       
  1582 
       
  1583 #if defined(TRACE_ENABLED)
       
  1584 		// print position every 1/16 of the partition size
       
  1585 		TInt64 printPos = Max((di->iEntry.iPartitionLen >> 4) & ~(KBufSize-1), KBufSize);
       
  1586 		if (((di->iEncryptEndPos - di->iEncryptStartPos)% printPos) == 0) 
       
  1587 			__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1588 #endif
       
  1589 //		__KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
       
  1590 
       
  1591 
       
  1592 		// Read a buffer, encrypt it, and then write it back
       
  1593 		// retry in case of media change
       
  1594 		const TInt KRetries = 5;
       
  1595 		r = KErrNotReady;
       
  1596 		for (TInt i=0; r == KErrNotReady && i < KRetries; i++)
       
  1597 			{
       
  1598 			r = Read(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1599 			if (r != KErrNone)
       
  1600 				continue;
       
  1601 
       
  1602 			TPtr8 des(iBuffer,len,len);
       
  1603 			if (di->Status() == ENfeEncrypting)
       
  1604 				EncryptBuffer(des);
       
  1605 			else
       
  1606 				DecryptBuffer(des);
       
  1607 			
       
  1608 			r = Write(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
       
  1609 			}
       
  1610 
       
  1611 		if (r == KErrNone)
       
  1612 			pos+= len;
       
  1613 
       
  1614 		if (di->iProgressToUiProperty)	// no iProgressToUiProperty for swap drive
       
  1615 			{
       
  1616 			TInt progress = (TInt) (KNfeDiskOpReady * (pos - di->iEntry.iPartitionBaseAddr) / di->iEntry.iPartitionLen);
       
  1617 //			__KTRACE_PRINT(Kern::Printf("NFE%d: Progess %d ", progress));
       
  1618 			((RPropertyRef*) (di->iProgressToUiProperty))->Set( progress ); // Return value ignored
       
  1619 			}
       
  1620 		}
       
  1621 	
       
  1622 	__KTRACE_PRINT(Kern::Printf("NFE%d: HandleDiskContent returned %d", iInstance, r));
       
  1623 
       
  1624 	// If not completed, start the idle timer & try again later
       
  1625 	if (r != KErrCompletion)
       
  1626 		iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
       
  1627 
       
  1628 //	Kern::SetThreadPriority(KNfeThreadPriority);	//*test*
       
  1629 	
       
  1630 	return r;
       
  1631 	}
       
  1632 
       
  1633 
       
  1634 
       
  1635 DECLARE_EXTENSION_PDD()
       
  1636 	{
       
  1637 	__KTRACE_PRINT(Kern::Printf("DECLARE_EXTENSION_PDD()"));
       
  1638 	return new DPhysicalDeviceMediaNFE;
       
  1639 	}
       
  1640 
       
  1641 DECLARE_STANDARD_EXTENSION()
       
  1642 	{
       
  1643 	__KTRACE_PRINT(Kern::Printf("DECLARE_STANDARD_EXTENSION()"));
       
  1644 
       
  1645 
       
  1646 	// Create the media driver factory object and register this with the kernel
       
  1647 	__KTRACE_PRINT(Kern::Printf("Creating NFE PDD"));
       
  1648 	DPhysicalDeviceMediaNFE* device = new DPhysicalDeviceMediaNFE;
       
  1649 	if (device == NULL)
       
  1650 		return KErrNoMemory;
       
  1651 	TInt r = Kern::InstallPhysicalDevice(device);
       
  1652 	__KTRACE_PRINT(Kern::Printf("Installing NFE PDD in extension init - name %s r:%d", NFE_DRIVENAME, r));
       
  1653 	if (r != KErrNone)
       
  1654 		return r;
       
  1655 
       
  1656 	TInt swapInstance = KErrNotFound;
       
  1657 #if defined (__DEMAND_PAGING__)
       
  1658 	swapInstance = SwapInstance();
       
  1659 #endif
       
  1660 
       
  1661 	DPrimaryMediaExt* primaryMedia[NFE_INSTANCE_COUNT];
       
  1662 	TInt instance;
       
  1663 
       
  1664 	for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1665 		{
       
  1666 		// Register this media device & define which drives we want to attach to.
       
  1667 		// These drives must already be registered with the local media subsystem
       
  1668 		// i.e. this media's kernel extension must be defined AFTER any attached
       
  1669 		// media's kernel extension in the appropriate .IBY file
       
  1670 		__KTRACE_PRINT(Kern::Printf("NFE%d: Creating NFE primary media", instance));
       
  1671 		DPrimaryMediaExt* pM = new DPrimaryMediaExt(instance);
       
  1672 		if (pM == NULL)
       
  1673 			return KErrNoMemory;
       
  1674 		primaryMedia[instance] = pM;
       
  1675 
       
  1676 		_LIT(KMediaThreadName,"NfeThread?");
       
  1677 		HBuf* pMediaThreadName = HBuf::New(KMediaThreadName);
       
  1678 		(*pMediaThreadName)[9] = (TUint8) ('0' + (TUint8) instance);
       
  1679 
       
  1680 		TInt r = Kern::DfcQInit(&pM->iNfeDfcQ,KNfeThreadPriority,pMediaThreadName);
       
  1681 		if (r != KErrNone)
       
  1682 			return r;
       
  1683 
       
  1684 #ifdef CPU_AFFINITY_ANY
       
  1685 		NKern::ThreadSetCpuAffinity((NThread*)(pM->iNfeDfcQ.iThread), KCpuAffinityAny);
       
  1686 #endif
       
  1687 		
       
  1688 
       
  1689 		pM->iDfcQ = &pM->iNfeDfcQ;
       
  1690 		pM->iMsgQ.Receive();
       
  1691 
       
  1692 
       
  1693 		const TInt* driveList = DriveList(instance);
       
  1694 		TInt driveCount = DriveCount(instance);
       
  1695 
       
  1696 		TBuf<4> driveName(_L("NFE?"));
       
  1697 		driveName[3] = (TUint8) ('0' + (TUint8) instance);
       
  1698 
       
  1699 		
       
  1700 		r = LocDrv::RegisterMediaDevice(
       
  1701 			MEDIA_DEVICE_NFE, 
       
  1702 			driveCount, driveList,
       
  1703 			pM, NFE_NUMMEDIA, driveName);
       
  1704 		if (r != KErrNone)
       
  1705 			return r;
       
  1706 
       
  1707 
       
  1708 #if defined (__DEMAND_PAGING__)
       
  1709 		if (PagingType(instance))
       
  1710 			{
       
  1711 			// Define which of the drives we have already attached to have code or data paging enabled 
       
  1712 			const TInt* pageDriveList = PageDriveList(instance);
       
  1713 			TInt pageDriveCount = PageDriveCount(instance);
       
  1714 
       
  1715 			r = LocDrv::RegisterPagingDevice(pM,pageDriveList,pageDriveCount,PagingType(instance),SECTOR_SHIFT,NFE_NUM_PAGES);
       
  1716 			__KTRACE_PRINT(Kern::Printf("NFE%d: Installing NFE PagingDevice in extension init - r:%d", pM->iInstance, r));
       
  1717 			// Ignore error if demand paging not supported by kernel
       
  1718 			if (r == KErrNotSupported)
       
  1719 				r = KErrNone;
       
  1720 			if (r != KErrNone)
       
  1721 				return r;
       
  1722 			}
       
  1723 
       
  1724 
       
  1725 #endif	// __NAND_DEMAND_PAGING__
       
  1726 
       
  1727 		/*
       
  1728 		If there is a swap partition we need to make sure all instances have their PartitionInfo() called
       
  1729 		so that we can flag the swap partition as 'encrypted' if there are any encrypted drives at all
       
  1730 		*/
       
  1731 		if (swapInstance != KErrNotFound)
       
  1732 			{
       
  1733 			TBuf8<sizeof(TLocalDriveCapsV6)> capsBuf;
       
  1734 			capsBuf.SetMax();
       
  1735 			capsBuf.FillZ();
       
  1736 			DLocalDrive::Caps(driveList[0], capsBuf);
       
  1737 			}
       
  1738 		}
       
  1739 		
       
  1740 
       
  1741 	// If we encounter an encrypted drive belonging to ANY NFE instance, then assume the swap partition is 
       
  1742 	// encrypted too. We need to do this because the swap partition has no equivalent of the boot sector
       
  1743 	if (swapInstance != KErrNotFound)
       
  1744 		{
       
  1745 		__KTRACE_PRINT(Kern::Printf("NFE: Searching for encrypted drives to determine whether swap partition should be encrypted..."));
       
  1746 		TBool encryptedDriveFound = EFalse;
       
  1747 		TNfeDriveInfo* swapDriveInfo = NULL;
       
  1748 		for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
       
  1749 			{
       
  1750 			DPrimaryMediaExt* pM = primaryMedia[instance];
       
  1751 			DMediaDriverNFE* mediaDriver = (DMediaDriverNFE*) pM->iDriver;
       
  1752 			__ASSERT_ALWAYS(mediaDriver, NFE_FAULT());
       
  1753 
       
  1754 			if (swapDriveInfo == NULL)
       
  1755 				swapDriveInfo = mediaDriver->GetSwapDrive();
       
  1756 
       
  1757 			for (TInt i=0; i<mediaDriver->iInfo.iDriveCount; i++)
       
  1758 				{
       
  1759 				TNfeDriveInfo& di = mediaDriver->iInfo.iDrives[i];
       
  1760 				__KTRACE_PRINT(Kern::Printf("NFE%d: Testing drive %d DriveLetter %c status %s", 
       
  1761 					instance, di.iLocalDriveNum, (TInt) DriveLetterToAscii(di.iDriveLetter), DriveStatus(di.Status()) ));
       
  1762 				if (di.Status() == ENfeEncrypted || di.Status() == ENfeEncrypting)
       
  1763 					encryptedDriveFound = ETrue;
       
  1764 				}
       
  1765 			}
       
  1766 		if (swapDriveInfo)
       
  1767 			{
       
  1768 			swapDriveInfo->SetStatus(encryptedDriveFound ? ENfeEncrypted : ENfeDecrypted);
       
  1769 			swapDriveInfo->iEncryptEndPos = swapDriveInfo->iEntry.iPartitionBaseAddr + swapDriveInfo->iEntry.iPartitionLen;
       
  1770 
       
  1771 			__KTRACE_PRINT(Kern::Printf("NFE: Setting swap partition state to %s...", DriveStatus(swapDriveInfo->Status())));
       
  1772 			}
       
  1773 		}
       
  1774 
       
  1775 
       
  1776 	return r;
       
  1777 	}
       
  1778 
       
  1779