--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mediaext/d_nfe.cpp Fri Apr 23 22:20:31 2010 +0100
@@ -0,0 +1,1779 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mediext\d_nfe.cpp
+//
+//
+
+#include <drivers/locmedia.h>
+#include <platform.h>
+#include <variantmediadef.h>
+#include "nfe.h"
+
+#if defined(_DEBUG)
+ #define TRACE_ENABLED
+#else
+#endif
+
+#if defined(TRACE_ENABLED)
+#define __KTRACE_PRINT(p) {p;}
+#else
+#define __KTRACE_PRINT(p)
+#endif
+
+
+
+
+// Variant parameters for test Media Extension Driver
+
+
+const TInt KNfeThreadPriority = 24; // same as file server
+const TInt KNfeDiskOpReady = 100; //100%
+//const TInt KNfeDiskOpStart = 0; //0%
+
+_LIT(KPddName, "Media.NFE");
+#define NFE_DRIVENAME "NFE"
+#define NFE_NUMMEDIA 1
+
+// Define the array of local drives which we're attaching to
+__ASSERT_COMPILE(sizeof(TNfeDeviceInfo) <= 256); // KMaxQueryDeviceLength
+
+// Define the array of local code-paging drives which we're attaching to
+#ifdef __DEMAND_PAGING__
+ __ASSERT_COMPILE(NFE_PAGEDRIVECOUNT <= TNfeDeviceInfo::ENfeMaxPartitionEntries);
+ __ASSERT_COMPILE(NFE_DRIVECOUNT >= NFE_PAGEDRIVECOUNT);
+ #define SECTOR_SHIFT 9
+#endif // #ifdef __DEMAND_PAGING__
+
+
+
+
+class DPrimaryMediaExt : public DPrimaryMediaBase
+ {
+public:
+ DPrimaryMediaExt(TInt aInstance);
+public:
+ TInt iInstance;
+ TDfcQue iNfeDfcQ;
+ };
+
+
+
+// Get the number of drives in the drive array belonging to this instance
+TInt DriveCount(TInt aInstance)
+ {
+ static const TInt NfeInstanceDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_DRIVE_COUNTS};
+ return NfeInstanceDriveCounts[aInstance];
+ }
+
+// Get a pointer to the first drive in the drive array belonging to this instance
+const TInt* DriveList(TInt aInstance)
+ {
+ static const TInt NfeDriveNumbers[NFE_DRIVECOUNT]={NFE_DRIVELIST};
+ TInt driveListOffset = 0;
+ for (TInt n=0; n<aInstance; n++)
+ driveListOffset+= DriveCount(n);
+ return NfeDriveNumbers + driveListOffset;
+ }
+
+const TInt* DriveLetterList(TInt aInstance)
+ {
+ static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
+ TInt driveListOffset = 0;
+ for (TInt n=0; n<aInstance; n++)
+ driveListOffset+= DriveCount(n);
+ return NfeDriveLetters + driveListOffset;
+ }
+
+TInt DriveLetter(TInt aIndex)
+ {
+ static const TInt NfeDriveLetters[NFE_DRIVECOUNT]={NFE_DRIVELETTERLIST};
+ return NfeDriveLetters[aIndex];
+ }
+
+TChar DriveLetterToAscii(TInt aDriveLetter)
+ {
+ return aDriveLetter >= 0 && aDriveLetter <= 25 ? aDriveLetter +'A' : '?';
+ }
+
+#ifdef __DEMAND_PAGING__
+ // Get the number of drives in the paged drive array belonging to this instance
+ TInt PageDriveCount(TInt aInstance)
+ {
+ #if NFE_PAGEDRIVECOUNT > 0
+ static const TInt NfeInstancePageDriveCounts[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGEDRIVE_COUNTS};
+ return NfeInstancePageDriveCounts[aInstance];
+ #else
+ return 0;
+ #endif
+ }
+
+ // Get a pointer to the first drive in the paged drive array belonging to this instance
+ const TInt* PageDriveList(TInt aInstance)
+ {
+ #if NFE_PAGEDRIVECOUNT > 0
+ static const TInt NfePageDriveNumbers[NFE_PAGEDRIVECOUNT]={NFE_PAGEDRIVELIST};
+ TInt driveListOffset = 0;
+ for (TInt n=0; n<aInstance; n++)
+ driveListOffset+= PageDriveCount(n);
+ return NfePageDriveNumbers + driveListOffset;
+ #else
+ return NULL;
+ #endif
+ }
+
+ // Get the number of paging type belonging to this instance
+ TInt PagingType(TInt aInstance)
+ {
+ #if NFE_PAGEDRIVECOUNT > 0
+ static const TInt NfeInstancePagingType[NFE_INSTANCE_COUNT]={NFE_INSTANCE_PAGING_TYPE};
+ return NfeInstancePagingType[aInstance];
+ #else
+ return 0;
+ #endif
+ }
+
+ // get the instance of the swap drive
+ TInt SwapInstance()
+ {
+ for (TInt i=0; i<NFE_INSTANCE_COUNT; i++)
+ if (PagingType(i) & DPagingDevice::EData)
+ return i;
+ return KErrNotFound;
+ }
+#endif // #ifdef __DEMAND_PAGING__
+
+
+const char* DriveStatus(TNfeDiskStatus aStatus)
+ {
+ const char* KNfeUnmounted = "Unmounted";
+ const char* KNfeDecrypted = "Decrypted";
+ const char* KNfeDecrypting = "Decrypting";
+ const char* KNfeEncrypted = "Encrypted";
+ const char* KNfeEncrypting = "Encrypting";
+ const char* KNfeWiping = "Wiping";
+ const char* KNfeCorrupted = "Corrupted";
+ const char* KNfeUnrecognised = "Unrecognised";
+
+ switch(aStatus)
+ {
+ case ENfeUnmounted:
+ return KNfeUnmounted;
+ case ENfeDecrypted:
+ return KNfeDecrypted;
+ case ENfeDecrypting:
+ return KNfeDecrypting;
+ case ENfeEncrypted:
+ return KNfeEncrypted;
+ case ENfeEncrypting:
+ return KNfeEncrypting;
+ case ENfeWiping:
+ return KNfeWiping;
+ case ENfeCorrupted:
+ return KNfeCorrupted;
+ default:
+ return KNfeUnrecognised;
+
+ }
+ }
+
+
+DPrimaryMediaExt::DPrimaryMediaExt(TInt aInstance) : iInstance(aInstance)
+ {
+ }
+
+
+#define NFE_FAULT() Kern::Fault("NFEMEDIA",__LINE__)
+
+// disk encryption/decryption/wiping is only performed after the following period of inactivity
+// NB USB Mass Storage tends to 'poll' the media driver by sending ECaps every second or so, so we need
+// to ensure this timeout period is significantly less to ensure the timer DFC thread gets a chance to run...
+const TInt KNotBusyInterval = 200; // 200 mS
+
+
+
+class DPhysicalDeviceMediaNFE : public DPhysicalDevice
+ {
+public:
+ DPhysicalDeviceMediaNFE();
+ virtual TInt Install();
+ virtual void GetCaps(TDes8& aDes) const;
+ virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
+ virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
+ virtual TInt Info(TInt aFunction, TAny* a1);
+ };
+
+
+class DMediaDriverNFE : public DMediaDriverExtension
+ {
+public:
+ class TPropertyObserver
+ {
+ public:
+ void Close();
+ static void PropertySubsCompleteFn(TAny* aPtr, TInt aReason);
+ public:
+ TInt iDriveIndex;
+ DMediaDriverNFE* iMediaExt;
+ RPropertyRef iProperty;
+ TPropertySubsRequest* iPropertySubsRequest;
+ TDfc* iPropertyDfc; // N.B. subscription call backs don't occur in our thread context, hence the need for this DFC
+ TInt iValue;
+ };
+
+public:
+ DMediaDriverNFE(TInt aMediaId);
+ ~DMediaDriverNFE();
+
+ // replacing pure virtual
+ virtual TInt Request(TLocDrvRequest& aRequest);
+ virtual TInt PartitionInfo(TPartitionInfo &anInfo);
+
+ TInt DoCreate(TInt aMediaId);
+ void Close();
+
+ TNfeDriveInfo* GetSwapDrive();
+
+private:
+ TInt HandleRead(TLocDrvRequest& aRequest);
+ TInt HandleWrite(TLocDrvRequest& aRequest);
+ TInt HandleFormat(TLocDrvRequest& aRequest);
+ TInt HandleCaps(TLocDrvRequest& aReq);
+
+
+ void EncryptBuffer(TDes8& aBuffer);
+ void DecryptBuffer(TDes8& aBuffer);
+
+ inline TUint8 EncryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
+ inline TUint8 DecryptByte(TUint8 aByte) {return (TUint8) (aByte ^ 0xDD);}
+ inline TInt DriveIndex(TInt aDriveNum) {return iDriveNumToIndex[aDriveNum];}
+
+ static void IdleTimerCallBack(TAny* aMediaDriver);
+ static void TimerDfcFunction(TAny* aMediaDriver);
+
+ // Publish & Subscribe stuff - used to listen to requests from UI
+ static void FromUiPropertyDfcFunction(TAny* aObserver);
+ void FromUiPropertyDfc(TPropertyObserver& aObserver);
+
+ // Publish & Subscribe stuff - used to listen to status setting from other NFE drives
+ static void StatusToUiPropertyDfcFunction(TAny* aObserver);
+ void StatusToUiPropertyDfc(TPropertyObserver& aObserver);
+
+ void StartEncrypting();
+ void StartDecrypting();
+
+ TInt HandleDiskContent(); // called from idle timer DFC
+
+ TNfeDriveInfo* NextDrive();
+
+ TBool AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen);
+
+ void SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus);
+
+ TBool ValidBootSector(TUint8* aBuffer);
+ TUint32 VolumeId(TUint8* aBuffer);
+ void CheckBootSector(TNfeDriveInfo &aDriveInfo);
+ TInt WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised = EFalse);
+
+private:
+ TInt iInstance; // media drive instance
+
+ // A local buffer use for encryting / decrypting
+ // For paging requests we need this to be page aligned, so allocate enough to cater for
+ // the worst case of up to 4K being wasted at the start of the buffer and the end
+ enum {KSectorSize = 512, KPageSize = 4096, KBufSize = 65536};
+ TUint8 iNonPageAlignedBuffer[KBufSize + KPageSize*2];
+ // a pointer to the start of the first page in iNonPageAlignedBuffer
+ TUint8* iBuffer;
+
+
+ // Idle timer & DFC for kicking an encryption pass
+ NTimer iIdleTimer;
+ TDfc iTimerDfc;
+
+ TInt iDriveIndex; // index of local drive number currently being encrypted
+ TInt iDriveNumToIndex[KMaxPartitionEntries]; // maps drive numbers to index
+
+ TBool iBusy;
+
+ const TInt* iDriveList; // pointer into the drives in NFE_DRIVELIST belonging to this media driver
+ const TInt* iDriveLetterList; // pointer into the drive letter in NFE_DRIVELETTERLIST belonging to this media driver
+
+ // Publish & subscribe stuff which handles drive command notification events from the UI
+ TPropertyObserver iFromUiPropertyObserver[NFE_DRIVECOUNT];
+
+ // Publish & subscribe stuff which handles drive status notification events from the other NFE drives
+ TPropertyObserver iStatusToUiPropertyObserver[NFE_DRIVECOUNT];
+
+ TBool iDriveFinalised;
+
+public:
+ // Partition information etc for drives this driver is attached to
+ TNfeDeviceInfo iInfo;
+ };
+
+
+
+class TBootSectorStatus
+ {
+public:
+ TUint8 iFatBootSectorData[128];
+
+ enum {ENfeBootSectorSignature = 0x2045464E}; // 'NFE '
+ TUint32 iSignature;
+
+ TNfeDiskStatus iStatus;
+ TBool iFinalised;
+ TInt64 iEncryptEndPos; // position of the last encrypted byte +1. Only written when device is powered down
+ };
+
+
+DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()
+ {
+ __KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::DPhysicalDeviceMediaNFE()"));
+ iUnitsMask=0x1;
+ iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
+ }
+
+/**
+Install the Internal NFE PDD.
+*/
+TInt DPhysicalDeviceMediaNFE::Install()
+ {
+ __KTRACE_PRINT(Kern::Printf(": TInt DPhysicalDeviceMediaNFE::Install()"));
+
+ return SetName(&KPddName);
+ }
+
+void DPhysicalDeviceMediaNFE::GetCaps(TDes8& /*aDes*/) const
+ {
+ }
+
+/**
+Create an NFE media driver.
+*/
+TInt DPhysicalDeviceMediaNFE::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
+ {
+ __KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Create()"));
+
+ if (!Kern::QueryVersionSupported(iVersion,aVer))
+ return KErrNotSupported;
+
+ TInt r=KErrNoMemory;
+
+ DMediaDriverNFE* pD = new DMediaDriverNFE(aMediaId);
+ aChannel=pD;
+ if (pD)
+ r=pD->DoCreate(aMediaId);
+
+ if (r == KErrNone)
+ pD->OpenMediaDriverComplete(KErrNone);
+
+ return r;
+ }
+
+TInt DPhysicalDeviceMediaNFE::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
+ {
+ TInt r;
+ if (!Kern::QueryVersionSupported(iVersion,aVer))
+ r = KErrNotSupported;
+ else if (aDeviceType == MEDIA_DEVICE_NFE)
+ return r = KErrNone;
+ else
+ r = KErrNotSupported;
+
+// __KTRACE_PRINT(Kern::Printf("DPhysicalDeviceMediaNFE::Validate() aDeviceType %d NfeDeviceType %d r %d", aDeviceType, MEDIA_DEVICE_NFE, r));
+ return r;
+ }
+
+TInt DPhysicalDeviceMediaNFE::Info(TInt aFunction, TAny*)
+//
+// Return the priority of this media driver
+//
+ {
+// __KTRACE_PRINT(Kern::Printf(": DPhysicalDeviceMediaNFE::Info()"));
+
+ if (aFunction==EPriority)
+ return KMediaDriverPriorityNormal;
+
+ if (aFunction==EMediaDriverPersistent)
+ return KErrNone;
+
+ return KErrNotSupported;
+ }
+
+DMediaDriverNFE::DMediaDriverNFE(TInt aMediaId) :
+ DMediaDriverExtension(aMediaId),
+ iInstance(((DPrimaryMediaExt*) iPrimaryMedia)->iInstance),
+ iIdleTimer(IdleTimerCallBack,this),
+ iTimerDfc(TimerDfcFunction,this,2),
+ iDriveList (DriveList(iInstance)),
+ iDriveLetterList (DriveLetterList(iInstance))
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DMediaDriverNFE()", iInstance));
+ iInfo.iDriveCount = DriveCount(iInstance);
+
+ __ASSERT_ALWAYS(Kern::RoundToPageSize(1) == KPageSize, NFE_FAULT());
+
+ // Align the buffer to a page boundary to improve efficiency for paging requests
+ iBuffer = &iNonPageAlignedBuffer[0];
+ iBuffer = (TUint8*) ((((TUint32) &iNonPageAlignedBuffer[0]) + KPageSize-1) & ~(KPageSize-1));
+ }
+
+DMediaDriverNFE::~DMediaDriverNFE()
+//
+// Destructor.
+//
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::~DMediaDriverNFE()", iInstance));
+
+ TInt i;
+ for (i=0; i<TNfeDeviceInfo::ENfeMaxPartitionEntries; i++)
+ {
+ RPropertyRef* property = (RPropertyRef*) iInfo.iDrives[i].iStatusToUiProperty;
+ if (property)
+ {
+ property->Delete();
+ delete property;
+ }
+ property = (RPropertyRef*) iInfo.iDrives[i].iToUiProperty;
+ if (property)
+ {
+ property->Delete();
+ delete property;
+ }
+ property = (RPropertyRef*) iInfo.iDrives[i].iProgressToUiProperty;
+ if (property)
+ {
+ property->Delete();
+ delete property;
+ }
+ }
+
+ for (i=0; i<NFE_DRIVECOUNT; i++)
+ {
+ iFromUiPropertyObserver[i].Close();
+ iStatusToUiPropertyObserver[i].Close();
+ }
+ }
+
+
+TInt CreateKey(RPropertyRef*& aProperty, TUint aKey)
+ {
+ aProperty = new RPropertyRef;
+ if (aProperty == NULL)
+ return KErrNoMemory;
+ TInt r = aProperty->Attach(KNfeUID, aKey);
+ if (r != KErrNone)
+ return r;
+
+ static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
+ r = aProperty->Define( RProperty::EInt, KPassPolicy, KPassPolicy );
+ if (r != KErrNone && r != KErrAlreadyExists)
+ return r;
+ return KErrNone;
+ }
+
+TInt DMediaDriverNFE::DoCreate(TInt /*aMediaId*/)
+//
+// Create the media driver.
+//
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: TInt DMediaDriverNFE::DoCreate()", iInstance));
+
+ // Associate the idle timer DFC with our thread
+ iTimerDfc.SetDfcQ(iPrimaryMedia->iDfcQ);
+
+ // Publish & Subscribe stuff - used to initiate an encryption pass from the test app
+ static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
+ TInt r;
+ TInt i;
+
+ TInt swapInstance = KErrNotFound;
+#if defined (__DEMAND_PAGING__)
+ swapInstance = SwapInstance();
+#endif
+
+ // **************************************************************************************
+ // Set up P&S publishers so we can publish the status for our drives
+ // **************************************************************************************
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi, ToUi, ProgressToUi P&S publisher & FromUi P&S observer", iInstance));
+
+ for (i = 0; i<DriveCount(iInstance); i++)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
+ TInt driveLetter = iDriveLetterList[i];
+ __KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(driveLetter)));
+
+ // no point setting up P&S for the swap drive
+ if (driveLetter == -1)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping P&S for swap partition", iInstance, i));
+ continue;
+ }
+
+ r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iStatusToUiProperty, NFE_KEY(driveLetter, KNfeStatusToUiKey));
+ if (r != KErrNone)
+ return r;
+
+ r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iToUiProperty, NFE_KEY(driveLetter, KNfeToUiKey));
+ if (r != KErrNone)
+ return r;
+
+ r = CreateKey((RPropertyRef*&) iInfo.iDrives[i].iProgressToUiProperty, NFE_KEY(driveLetter, KNfeProgressToUiKey));
+ if (r != KErrNone)
+ return r;
+
+ TPropertyObserver& observer = iFromUiPropertyObserver[i];
+ observer.iDriveIndex = i;
+ observer.iMediaExt = this;
+ observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
+ if (observer.iPropertySubsRequest == NULL)
+ return KErrNoMemory;
+
+ observer.iPropertyDfc = new TDfc(FromUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
+ if (observer.iPropertyDfc == NULL)
+ return KErrNoMemory;
+
+ r = observer.iProperty.Attach(KNfeUID, NFE_KEY(driveLetter, KNfeToThreadKey));
+ if (r != KErrNone)
+ return r;
+ r = observer.iProperty.Define(
+ RProperty::EInt,
+ KPassPolicy,
+ KPassPolicy);
+ if (r != KErrNone && r != KErrAlreadyExists)
+ return r;
+
+ r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
+ if (r != KErrNone)
+ return r;
+ }
+
+ // **************************************************************************************
+ // If this instance owns the swap partition,
+ // set up P&S listeners so we can get status notification events from the other drives
+ // **************************************************************************************
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Setting up StatusToUi P&S observer", iInstance));
+
+ for (i = 0; i < (iInstance == swapInstance ? NFE_DRIVECOUNT : -1); i++)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d:drive index %d", iInstance, i));
+ __KTRACE_PRINT(Kern::Printf("NFE%d:drive letter %c", iInstance, (TInt) DriveLetterToAscii(DriveLetter(i))));
+
+ // no point setting up P&S for the swap drive
+ if (DriveLetter(i) == -1)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Skipping StatusToUi P&S observer for swap partition", iInstance, i));
+ continue;
+ }
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: i %d, Setting up StatusToUi P&S observer for drive %c", iInstance, i, (TInt) DriveLetterToAscii(DriveLetter(i))));
+ TPropertyObserver& observer = iStatusToUiPropertyObserver[i];
+ observer.iDriveIndex = i;
+ observer.iMediaExt = this;
+ observer.iPropertySubsRequest = new TPropertySubsRequest(TPropertyObserver::PropertySubsCompleteFn, &observer);
+ if (observer.iPropertySubsRequest == NULL)
+ return KErrNoMemory;
+
+ observer.iPropertyDfc = new TDfc(StatusToUiPropertyDfcFunction,&observer,iPrimaryMedia->iDfcQ,2);
+ if (observer.iPropertyDfc == NULL)
+ return KErrNoMemory;
+
+ r = observer.iProperty.Attach(KNfeUID, NFE_KEY(DriveLetter(i), KNfeStatusToUiKey));
+ if (r != KErrNone)
+ return r;
+ r = observer.iProperty.Define(
+ RProperty::EInt,
+ KPassPolicy,
+ KPassPolicy);
+ if (r != KErrNone && r != KErrAlreadyExists)
+ return r;
+
+ r = observer.iProperty.Subscribe(*observer.iPropertySubsRequest);
+ if (r != KErrNone)
+ return r;
+ }
+
+ return(KErrNone);
+ }
+
+void DMediaDriverNFE::TPropertyObserver::Close()
+ {
+ iProperty.Close();
+ delete iPropertyDfc;
+ iPropertyDfc = NULL;
+ delete iPropertySubsRequest;
+ iPropertySubsRequest = NULL;
+ }
+
+void DMediaDriverNFE::TPropertyObserver::PropertySubsCompleteFn(TAny* aPtr, TInt /*aReason*/)
+ {
+ TPropertyObserver* self = (TPropertyObserver*) aPtr;
+ // Queue a DFC to ensure we're running in the correct thread
+ self->iPropertyDfc->Enque();
+ }
+
+void DMediaDriverNFE::FromUiPropertyDfcFunction(TAny* aObserver)
+ {
+ TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
+ observer.iMediaExt->FromUiPropertyDfc(observer);
+ }
+
+void DMediaDriverNFE::FromUiPropertyDfc(TPropertyObserver& aObserver)
+ {
+ // Get the value of request from the UI
+ TInt err = aObserver.iProperty.Get(aObserver.iValue);
+
+ TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
+ __ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
+
+ TInt driveLetter = iDriveLetterList[aObserver.iDriveIndex];
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::FromUiPropertyDfc() cmd %d driveLetter %c",
+ iInstance, aObserver.iValue, (TInt) DriveLetterToAscii(driveLetter)));
+
+ // is this our drive letter ?
+ TInt driveCount = DriveCount(iInstance);
+ TNfeDriveInfo* driveInfo = NULL;
+
+ for (TInt i=0; i<driveCount; i++)
+ {
+ TInt myDriveLetter = iDriveLetterList[i];
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Comparing drive %c with myDrive %c", iInstance, (TInt) DriveLetterToAscii(driveLetter), (TInt) DriveLetterToAscii(myDriveLetter)));
+
+ if (myDriveLetter == driveLetter)
+ {
+ TInt driveNumber = iDriveList[i];
+ driveInfo = &iInfo.iDrives[iDriveNumToIndex[driveNumber]];
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Drive Match found driveNumber %d", iInstance, driveInfo->iLocalDriveNum));
+
+ __ASSERT_ALWAYS(driveInfo->iProgressToUiProperty, NFE_FAULT());
+ ((RPropertyRef*) (driveInfo->iProgressToUiProperty))->Set(0);
+ // Wake up the possibly waiting client, whether or not the request
+ // was successfull.
+ ((RPropertyRef*) (driveInfo->iToUiProperty))->Set( err ); // Return value ignored
+ break;
+ }
+ }
+
+
+ __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));
+
+ if (err == KErrNone && aObserver.iValue == ENfeEncryptDisk && driveInfo != NULL)
+ {
+ if (driveInfo->Status() == ENfeDecrypted)
+ {
+ SetStatus(*driveInfo, ENfeEncrypting);
+ StartEncrypting();
+ }
+ }
+ if (err == KErrNone && aObserver.iValue == ENfeDecryptDisk && driveInfo != NULL)
+ {
+ if (driveInfo->Status() == ENfeEncrypted)
+ {
+ SetStatus(*driveInfo, ENfeDecrypting);
+ StartDecrypting();
+ }
+ }
+ }
+
+
+void DMediaDriverNFE::StatusToUiPropertyDfcFunction(TAny* aObserver)
+ {
+ TPropertyObserver& observer = *(TPropertyObserver*) aObserver;
+ observer.iMediaExt->StatusToUiPropertyDfc(observer);
+ }
+
+void DMediaDriverNFE::StatusToUiPropertyDfc(TPropertyObserver& aObserver)
+ {
+ // Get the value of request from the UI
+ TInt err = aObserver.iProperty.Get(aObserver.iValue);
+
+ TInt r = aObserver.iProperty.Subscribe(*aObserver.iPropertySubsRequest);
+ __ASSERT_ALWAYS(r == KErrNone, NFE_FAULT());
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::StatusToUiPropertyDfc() status %d driveLetter %c",
+ iInstance, aObserver.iValue, DriveLetter(aObserver.iDriveIndex) >=0 ? DriveLetter(aObserver.iDriveIndex)+'A' : '?'));
+
+
+ __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));
+
+ if (err == KErrNone && (aObserver.iValue == ENfeEncrypted || aObserver.iValue == ENfeEncrypting))
+ {
+ // If any drive is being or is already encrypted then we have to encrypt the swap partition...
+ TNfeDriveInfo* diSwap = GetSwapDrive();
+ if (diSwap != NULL && diSwap->Status() == ENfeDecrypted)
+ {
+ SetStatus(*diSwap, ENfeEncrypting);
+ StartEncrypting();
+ }
+ }
+ }
+
+
+void DMediaDriverNFE::Close()
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::Close()", iInstance));
+ DMediaDriverExtension::Close();
+ }
+
+
+void DMediaDriverNFE::SetStatus(TNfeDriveInfo& aDi, TNfeDiskStatus aStatus)
+ {
+ if (aStatus != aDi.Status())
+ {
+ aDi.SetStatus(aStatus);
+ __KTRACE_PRINT(Kern::Printf("NFE%d: SetStatus = %s", iInstance, DriveStatus(aDi.Status())));
+ }
+ }
+
+void TNfeDriveInfo::SetStatus(TNfeDiskStatus aStatus)
+ {
+ iStatus = aStatus;
+ if (IsUDADrive())
+ {
+ // Update the status pub&sub variable for UI
+ __ASSERT_ALWAYS(iStatusToUiProperty, NFE_FAULT());
+ ((RPropertyRef*) iStatusToUiProperty)->Set(aStatus);
+ }
+ }
+
+
+
+
+TInt DMediaDriverNFE::Request(TLocDrvRequest& aReq)
+ {
+// __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()));
+
+ TInt r = KErrNotSupported;
+
+ TInt reqId = aReq.Id();
+ TNfeDriveInfo& di = iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
+
+ switch (reqId)
+ {
+#if defined(__DEMAND_PAGING__)
+ case DMediaPagingDevice::ERomPageInRequest:
+ BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
+ r=HandleRead(aReq);
+ break;
+
+ case DMediaPagingDevice::ECodePageInRequest:
+ BTraceContext8(BTrace::EPagingMedia,BTrace::EPagingMediaPagingMedDrvBegin,MEDIA_DEVICE_NFE,&aReq);
+ r=HandleRead(aReq);
+ break;
+
+#endif // __DEMAND_PAGING__
+
+ case DLocalDrive::ERead:
+ r=HandleRead(aReq);
+ break;
+
+ case DLocalDrive::EWrite:
+ WriteEncryptionStatusToBootSector(di, EFalse); // a write to the drive clears the finalised state
+ r=HandleWrite(aReq);
+ break;
+
+ case DLocalDrive::ECaps:
+ r = HandleCaps(aReq);
+ break;
+
+ case DLocalDrive::EFormat:
+ r = HandleFormat(aReq);
+ break;
+
+ // API used by T_NFE to query state etc.
+ case DLocalDrive::EQueryDevice:
+ switch((TInt) aReq.iArg[0])
+ {
+ case EQueryNfeDeviceInfo:
+ {
+ TNfeDeviceInfo& deviceInfo = *(TNfeDeviceInfo*) aReq.RemoteDes();
+ iInfo.iMediaSizeInBytes = iTotalSizeInBytes;
+ deviceInfo = iInfo;
+
+ r = KErrCompletion;
+ break;
+ }
+ case RLocalDrive::EQueryFinaliseDrive:
+ {
+// TLocalDriveFinaliseInfo& finaliseInfo = *(TLocalDriveFinaliseInfo*) aReq.RemoteDes();
+// __KTRACE_PRINT(Kern::Printf("NFE%d: EQueryFinaliseDrive iMode %d", iInstance, finaliseInfo.iMode));
+
+ // write to boot sector to indicate that the drive has ben finalised
+ WriteEncryptionStatusToBootSector(di, ETrue);
+ }
+ default:
+ r = KErrNotSupported;
+ break;
+ }
+ break;
+
+ default:
+ r = ForwardRequest(aReq);
+ break;
+ }
+
+// __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::DoRequest() : ret: %d", iInstance, r));
+
+ if (!di.iDriveFinalised && iBusy)
+ {
+ // Restart the idle timer after processing a request
+ iIdleTimer.Cancel();
+ iTimerDfc.Cancel();
+ iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
+ }
+
+ return r;
+ }
+
+/**
+PartitionInfo()
+
+ Reads the partition information from the attached drive(s).
+ Note: this method is also called when a removable card is removed, so can
+ be used to detect a memory card insertions/removals. Assumes the swap
+ partition is encrypted if any encrypted FAT drives are found
+*/
+TInt DMediaDriverNFE::PartitionInfo(TPartitionInfo& aInfo)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DMediaDriverNFE::PartitionInfo()", iInstance));
+
+ TInt r = DoDrivePartitionInfo(aInfo);
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DoDrivePartitionInfo() r %d", iInstance, r));
+ if (r != KErrNone)
+ return r;
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: *** Slave drives partition info ***", iInstance));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iMediaSizeInBytes %lx", iInstance, aInfo.iMediaSizeInBytes));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionCount %d", iInstance, aInfo.iPartitionCount));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: ", iInstance));
+
+ TInt i;
+
+ __ASSERT_DEBUG(aInfo.iPartitionCount <= TNfeDeviceInfo::ENfeMaxPartitionEntries, NFE_FAULT());
+ for (i=0; i<aInfo.iPartitionCount; i++)
+ {
+ TInt driveNum = iDriveList[i];
+ iDriveNumToIndex[driveNum] = i;
+
+ TNfeDriveInfo& di = iInfo.iDrives[i];
+
+ di.iDriveFinalised = EFalse; // a remount clears the finalised state
+
+ // Make a copy of the TPartitionEntry
+ di.iEntry = aInfo.iEntry[i];
+
+
+ // save the local drive number
+ di.iLocalDriveNum = driveNum;
+ di.iDriveLetter = iDriveLetterList[i];
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DriveNum %d", iInstance, driveNum));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: DriveLetter %c", iInstance, (TInt) DriveLetterToAscii(di.iDriveLetter)));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionBaseAddr %lX", iInstance, di.iEntry.iPartitionBaseAddr));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionLen %lx", iInstance, di.iEntry.iPartitionLen));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iPartitionType %x", iInstance, di.iEntry.iPartitionType));
+
+
+ // If the drive was removed, reset it's state
+ if (di.iEntry.iPartitionType == KPartitionTypeEmpty)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Empty Partition, setting state to ENfeUnmounted", iInstance));
+ SetStatus(di, ENfeUnmounted);
+ }
+
+ // Is this an unencrypted FAT partition ?
+ if (di.IsUDADrive())
+ {
+ r = Read(di.iLocalDriveNum, di.iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
+ if (r != KErrNone)
+ return r;
+ CheckBootSector(di);
+ }
+
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: status = %s", iInstance, DriveStatus(di.Status())));
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptStartPos %lX", iInstance, di.iEncryptStartPos));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: iEncryptEndPos %lX", iInstance, di.iEncryptEndPos));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: ", iInstance));
+ }
+
+
+
+#ifdef COMPOSITE_DRIVES
+ // Accumulate the sizes of consecutive FAT drives & report the accumulated size back in the first FAT partition
+ for (i=0; i<aInfo.iPartitionCount; i++)
+ {
+ aInfo.iEntry[i] = iInfo.iDrives[i].iEntry;
+
+ if (iInfo.iDrives[i].IsUDADrive())
+ {
+ aInfo.iEntry[i].iPartitionLen = 0;
+ for (TInt j=i; j<aInfo.iPartitionCount; j++)
+ {
+ if (iInfo.iDrives[j].IsUDADrive())
+ {
+ aInfo.iEntry[i].iPartitionLen+= iInfo.iDrives[j].iEntry.iPartitionLen;
+ }
+ }
+ iInfo.iDrives[i].iCompositeSize = aInfo.iEntry[i].iPartitionLen;
+ i = j;
+ }
+ }
+#endif
+
+
+ SetTotalSizeInBytes(aInfo.iMediaSizeInBytes);
+
+
+ return KErrCompletion; // synchronous completion
+ }
+
+/**
+HandleCaps() -
+
+Return the Caps for a particular drive
+
+Queries the caps from the attached drive, ORs in appropriate paging flags & returns
+*/
+TInt DMediaDriverNFE::HandleCaps(TLocDrvRequest& aReq)
+ {
+ // Get caps from slave drive
+ // NB if we didn't want to alter anything then we could just call ForwardRequest(aReq);
+ TBuf8<sizeof(TLocalDriveCapsV6)> slaveCapsBuf;
+ TLocalDriveCapsV6& slaveCaps = *(TLocalDriveCapsV6*) slaveCapsBuf.Ptr();
+ slaveCapsBuf.SetMax();
+ slaveCapsBuf.FillZ();
+ TInt r = Caps(aReq.Drive()->iDriveNumber, slaveCapsBuf);
+ if (r != KErrNone)
+ return r;
+
+#ifdef COMPOSITE_DRIVES
+ TInt driveNum = aReq.Drive()->iDriveNumber;
+ TInt driveIndex = DriveIndex(driveNum);
+ if (iInfo.iDrives[driveIndex].iCompositeSize)
+ slaveCaps.iSize = iInfo.iDrives[driveIndex].iCompositeSize;
+#endif
+
+ // copy slave caps to returned caps
+ TLocalDriveCapsV6& caps = *(TLocalDriveCapsV6*)aReq.RemoteDes();
+ caps = slaveCaps;
+
+ // set the paging flags
+#ifdef __DEMAND_PAGING__
+ TLocDrv& drive = *aReq.Drive();
+ if (drive.iPrimaryMedia->iPagingMedia)
+ caps.iMediaAtt|=KMediaAttPageable;
+ if (drive.iPagingDrv)
+ caps.iDriveAtt|=KDriveAttPageable;
+#endif // __DEMAND_PAGING__
+
+ return KErrCompletion;
+ }
+
+
+/**
+AdjustRequest() -
+
+Adjusts position & length if a request crosses these boundaries:
+- the start of the partition (if RLocalDrive::ELocDrvWholeMedia set)
+- the current encrytion point (iEncryptEndPos) N.B. this will point to the end of the partition
+ if the drive is fully encrypted
+
+For composite drives, it also adjusts the position, length & drive number as appropriate to cater for
+crossing partition boundaries
+
+returns ETrue if buffer needs encrypting/decrypting
+*/
+
+TBool DMediaDriverNFE::AdjustRequest(TNfeDriveInfo*& aDriveInfo, TInt64& aCurrentPos, TInt64& aCurrentLen)
+ {
+#ifdef COMPOSITE_DRIVES
+ while (aCurrentPos >= aDriveInfo->iEntry.iPartitionLen)
+ {
+ aCurrentPos-= aDriveInfo->iEntry.iPartitionLen;
+ aDriveInfo++;
+ }
+ if (aCurrentPos + aCurrentLen > aDriveInfo->iEntry.iPartitionLen)
+ aCurrentLen = aDriveInfo->iEntry.iPartitionLen - aCurrentPos;
+#endif
+
+ // do we need to encrypt/decrypt this buffer ?
+ TBool encodeBuffer = EFalse;
+
+ if ((aDriveInfo->Status() == ENfeEncrypted) || aDriveInfo->Status() == ENfeEncrypting)
+ {
+// __ASSERT_DEBUG(aDriveInfo->iEncryptEndPos <= aDriveInfo->iEntry.iPartitionBaseAddr + aDriveInfo->iEntry.iPartitionLen, NFE_FAULT());
+
+ if (aCurrentPos < aDriveInfo->iEncryptStartPos)
+ {
+ aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptStartPos - aCurrentPos);
+ encodeBuffer = EFalse;
+ }
+ else if (aCurrentPos < aDriveInfo->iEncryptEndPos)
+ {
+ aCurrentLen = Min(aCurrentLen, aDriveInfo->iEncryptEndPos - aCurrentPos);
+ encodeBuffer = ETrue;
+ }
+ else
+ {
+ encodeBuffer = EFalse;
+ }
+ }
+
+ return encodeBuffer;
+ }
+
+
+TInt DMediaDriverNFE::HandleRead(TLocDrvRequest& aReq)
+ {
+ TInt r = KErrNone;
+ TInt64 currentPos = aReq.Pos();
+ TInt64 remainingLength = aReq.Length();
+ TInt desPos = 0;
+ TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
+
+// __KTRACE_PRINT(Kern::Printf("NFE%d: HandleRead pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
+
+
+ di->iReadRequestCount++;
+
+ if (aReq.Flags() & TLocDrvRequest::ECodePaging)
+ di->iCodePagingRequesCount++;
+ if (aReq.Flags() & TLocDrvRequest::EDataPaging)
+ di->iDataPagingReadRequestCount++;
+
+
+ // just forward the request if the drive is not encrypted
+ if (di->Status() == ENfeDecrypted)
+ return ForwardRequest(aReq);
+
+
+ while(remainingLength)
+ {
+ TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
+
+ TBool decryptBuffer = AdjustRequest(di, currentPos, currentLength);
+
+ // Read from attached drive
+#ifdef __DEMAND_PAGING__
+ if (DMediaPagingDevice::PagingRequest(aReq))
+ r = ReadPaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
+ else
+#endif
+ r = Read(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
+ if(r != KErrNone)
+ break;
+
+ TPtr8 des(iBuffer, I64LOW(currentLength), I64LOW(currentLength));
+
+ // decrypt buffer
+ if (decryptBuffer)
+ DecryptBuffer(des);
+
+ // write back to user
+ r = aReq.WriteRemote(&des, desPos);
+ if(r != KErrNone)
+ break;
+
+ remainingLength-= currentLength;
+ currentPos+= currentLength;
+ desPos+= I64LOW(currentLength);
+ }
+
+ return r == KErrNone ? KErrCompletion : r;
+ }
+
+TInt DMediaDriverNFE::HandleWrite(TLocDrvRequest& aReq)
+ {
+ TInt r = KErrNone;
+ TInt64 currentPos = aReq.Pos();
+ TInt64 remainingLength = aReq.Length();
+ TInt desPos = 0;
+ TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
+
+// __KTRACE_PRINT(Kern::Printf("NFE%d: HandleWrite pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
+
+
+ di->iWriteRequestCount++;
+ if (aReq.Flags() & TLocDrvRequest::EDataPaging)
+ di->iDataPagingWriteRequestCount++;
+
+
+ // just forward the request if the drive is not encrypted
+ if (di->Status() == ENfeDecrypted)
+ return ForwardRequest(aReq);
+
+ while(remainingLength)
+ {
+ TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
+
+ TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
+
+ // read from user
+ TPtr8 des(iBuffer,0,I64LOW(currentLength));
+ r = aReq.ReadRemote(&des, desPos);
+ if(r != KErrNone)
+ break;
+
+ // get the length of data read from the user in case user's
+ // descriptor is shorter than advertised
+ currentLength = des.Length();
+ if (currentLength == 0)
+ break;
+
+ // writing to sector zero ?
+ if (currentPos >= di->iEntry.iPartitionBaseAddr &&
+ currentPos < di->iEntry.iPartitionBaseAddr + KSectorSize &&
+ di->IsUDADrive())
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Write to sector #0 detected", iInstance));
+
+
+ TUint8* bootSector = iBuffer;
+ TUint8 bootSectorBuffer[KSectorSize];
+ // writing partial sector ?
+ if (currentPos > di->iEntry.iPartitionBaseAddr || currentLength < KSectorSize)
+ {
+ bootSector = bootSectorBuffer;
+ r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) bootSector, KSectorSize);
+ if(r != KErrNone)
+ break;
+ TInt64 readLen = KSectorSize;
+ TBool encryptBuffer = AdjustRequest(di, di->iEntry.iPartitionBaseAddr, readLen);
+ if (encryptBuffer)
+ {
+ TPtr8 des(bootSectorBuffer,KSectorSize,KSectorSize);
+ DecryptBuffer(des);
+ }
+ TInt sectorOffset = (TInt) (currentPos - di->iEntry.iPartitionBaseAddr);
+ TInt64 copyLen = currentLength;
+ if (copyLen > KSectorSize-sectorOffset)
+ copyLen = KSectorSize-sectorOffset;
+ memcpy(bootSectorBuffer+sectorOffset, iBuffer, (TInt) copyLen);
+ }
+
+ if ((di->Status() == ENfeUnmounted || di->Status() == ENfeCorrupted) &&
+ ValidBootSector(bootSector))
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Setting status to ENfeDecrypted", iInstance ));
+ di->SetStatus(ENfeDecrypted);
+ }
+ di->iUniqueID = VolumeId(bootSector); // update the Volume ID
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Setting Volume ID to %08X", iInstance, di->iUniqueID ));
+ TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
+ if (di->Status() == ENfeEncrypting || di->Status() == ENfeDecrypting)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Adding NFE status record to boot sector", iInstance ));
+ bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
+ bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
+ bootSectorStatus->iStatus = di->Status();
+ bootSectorStatus->iFinalised = EFalse;
+ }
+ }
+
+ // encrypt the buffer
+ if (encryptBuffer)
+ EncryptBuffer(des);
+
+ // write the data to the attached drive
+#ifdef __DEMAND_PAGING__
+ if (DMediaPagingDevice::PagingRequest(aReq))
+ r = WritePaged(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
+ else
+#endif
+ r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
+ if(r != KErrNone)
+ break;
+
+ remainingLength-= currentLength;
+ currentPos+= currentLength;
+ desPos+= I64LOW(currentLength);
+ }
+
+ return r == KErrNone ? KErrCompletion : r;
+ }
+
+TInt DMediaDriverNFE::HandleFormat(TLocDrvRequest& aReq)
+ {
+ TInt r = KErrNone;
+ TInt64 currentPos = aReq.Pos();
+ TInt64 remainingLength = aReq.Length();
+ TNfeDriveInfo* di = &iInfo.iDrives[DriveIndex(aReq.Drive()->iDriveNumber)];
+
+// __KTRACE_PRINT(Kern::Printf("NFE%d: HandleFormat pos %lx len %lx status %d", iInstance, currentPos, remainingLength, di->Status()));
+
+
+ // just forward the request if the drive is not encrypted
+ if (di->Status() == ENfeDecrypted)
+ return ForwardRequest(aReq);
+
+ // otherwise create a buffer containing NULLs, encrypt it and write that to the attached drive
+ while(remainingLength && r == KErrNone)
+ {
+ TInt64 currentLength = (remainingLength <= KBufSize ? remainingLength : KBufSize);
+
+ TBool encryptBuffer = AdjustRequest(di, currentPos, currentLength);
+
+ memclr(iBuffer, KBufSize);
+ TPtr8 des(iBuffer,KBufSize,KBufSize);
+
+ if (encryptBuffer)
+ EncryptBuffer(des);
+
+ r = Write(di->iLocalDriveNum, currentPos, (TLinAddr) iBuffer, I64LOW(currentLength));
+ if(r != KErrNone)
+ break;
+
+ remainingLength-= currentLength;
+ currentPos+= currentLength;
+ }
+
+ return r == KErrNone ? KErrCompletion : r;
+ }
+
+
+void DMediaDriverNFE::EncryptBuffer(TDes8& aBuffer)
+ {
+ TInt len = aBuffer.Length();
+ for(TInt i=0; i<len; i++)
+ aBuffer[i] = EncryptByte(aBuffer[i]);
+ }
+
+void DMediaDriverNFE::DecryptBuffer(TDes8& aBuffer)
+ {
+ TInt len = aBuffer.Length();
+ for(TInt i=0; i<len; i++)
+ aBuffer[i] = DecryptByte(aBuffer[i]);
+ }
+
+
+TNfeDriveInfo* DMediaDriverNFE::GetSwapDrive()
+ {
+ for (TInt i=0; i<iInfo.iDriveCount; i++)
+ {
+ TNfeDriveInfo& di = iInfo.iDrives[i];
+ if (di.iEntry.iPartitionType == KPartitionTypePagedData)
+ {
+ return &di;
+ }
+ }
+ return NULL; // swap drive not found
+ }
+
+/**
+Get the first/next drive to encrypt
+*/
+
+TNfeDriveInfo* DMediaDriverNFE::NextDrive()
+ {
+ for (iDriveIndex = 0; iDriveIndex<iInfo.iDriveCount; iDriveIndex++)
+ {
+ TNfeDriveInfo& di = iInfo.iDrives[iDriveIndex];
+ TNfeDiskStatus status = iInfo.iDrives[iDriveIndex].Status();
+ if (status == ENfeEncrypting || status == ENfeDecrypting)
+ {
+ di.iEncryptStartPos = di.iEncryptEndPos = di.iEntry.iPartitionBaseAddr;
+
+ // write to boot sector to indicate we are encrypting/decrypting this drive
+ WriteEncryptionStatusToBootSector(di);
+
+ return &di;
+ }
+ }
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting / decrypting", iInstance));
+ iBusy = EFalse;
+ return NULL;
+ }
+
+
+/**
+Finds the first unencrypted drive & kicks off the idle timer -
+when this expires the encryption of the drive will start
+*/
+void DMediaDriverNFE::StartEncrypting()
+ {
+ // start encrypting if not already doing so
+ if (!iBusy)
+ {
+ iBusy = ETrue;
+ TNfeDriveInfo* di = NextDrive();
+ if (di)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Start encrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
+ iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
+ }
+ }
+ }
+
+/**
+Finds the first unencrypted drive & kicks off the idle timer -
+when this expires the encryption of the drive will start
+*/
+void DMediaDriverNFE::StartDecrypting()
+ {
+ // start encrypting if not already doing so
+ if (!iBusy)
+ {
+ iBusy = ETrue;
+ TNfeDriveInfo* di = NextDrive();
+ if (di)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Start decrypting drive %d...", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
+ iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
+ }
+ }
+ }
+
+/**
+Idle timer callback
+Kicks off a DFC to ensure we are running in the correct thread
+*/
+void DMediaDriverNFE::IdleTimerCallBack(TAny* aMediaDriver)
+ {
+ ((DMediaDriverNFE*)aMediaDriver)->iTimerDfc.Add();
+ }
+
+/**
+Idle timer DFC
+*/
+void DMediaDriverNFE::TimerDfcFunction(TAny* aMediaDriver)
+ {
+ ((DMediaDriverNFE*) aMediaDriver)->HandleDiskContent();
+ }
+
+
+TBool DMediaDriverNFE::ValidBootSector(TUint8* aBuffer)
+ {
+ if (aBuffer[0] == 0xEB || aBuffer[0] == 0xE9)
+ return ETrue;
+ else
+ return EFalse;
+ }
+
+
+TUint32 DMediaDriverNFE::VolumeId(TUint8* aBuffer)
+ {
+ TUint16 rootDirEntries;
+ TUint32 uniqueID;
+ memcpy(&rootDirEntries,&aBuffer[17], 2); // 17 TUint16 iRootDirEntries
+ TBool fat32 = rootDirEntries == 0;
+ TInt pos = fat32 ? 67 : 39; // get position of VolumeID
+ memcpy(&uniqueID,&aBuffer[pos],4);
+ return uniqueID;
+ }
+
+void DMediaDriverNFE::CheckBootSector(TNfeDriveInfo &aDi)
+ {
+ TNfeDiskStatus fatBootSectorStatus = ENfeDecrypted;
+
+ // Try to determine whether the FAT boot sector is encypted
+ if (ValidBootSector(iBuffer))
+ {
+ fatBootSectorStatus = ENfeDecrypted;
+ __KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is decrypted", iInstance));
+ }
+ else
+ {
+ TPtr8 des(iBuffer, KSectorSize, KSectorSize);
+ DecryptBuffer(des);
+ if (ValidBootSector(iBuffer))
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is encrypted", iInstance));
+ fatBootSectorStatus = ENfeEncrypted;
+ }
+ else
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: FAT Boot sector is corrupted", iInstance));
+ fatBootSectorStatus = ENfeCorrupted;
+ }
+ }
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: fatBootSectorStatus %d", iInstance, fatBootSectorStatus));
+
+ // Find out whether the volume has changed
+ TUint32 uniqueID = VolumeId(iBuffer);
+ TBool volumeChanged = uniqueID != aDi.iUniqueID;
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Old Volume ID %08X", iInstance, aDi.iUniqueID));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: New Volume ID %08X", iInstance, uniqueID));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: volumeChanged %d", iInstance, volumeChanged));
+ aDi.iUniqueID = uniqueID;
+
+
+
+ TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iSignature %08X", iInstance, bootSectorStatus->iSignature));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iStatus %d", iInstance, bootSectorStatus->iStatus));
+ __KTRACE_PRINT(Kern::Printf("NFE%d: CheckBootSector, iEncryptEndPos %lx", iInstance, bootSectorStatus->iEncryptEndPos));
+
+
+ /*
+ If there IS NFE info in the boot sector, restore the encryption settings -
+ unless the 'finalised' flag is clear which indicates that the media was removed or power was lost
+ while encrypting the device...
+
+ If there is no NFE info in the boot sector and there has been a volume change, then we can decide
+ whether the drive is encrypted/decrypted/corrupt by examining the boot sector
+ */
+ if (volumeChanged &&
+ fatBootSectorStatus != ENfeCorrupted &&
+ bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
+ !bootSectorStatus->iFinalised)
+ {
+ SetStatus(aDi, ENfeCorrupted);
+ }
+ else if (volumeChanged &&
+ fatBootSectorStatus != ENfeCorrupted &&
+ bootSectorStatus->iFinalised &&
+ bootSectorStatus->iSignature == TBootSectorStatus::ENfeBootSectorSignature &&
+ (bootSectorStatus->iStatus == ENfeDecrypting || bootSectorStatus->iStatus == ENfeEncrypting))
+ {
+ SetStatus(aDi, bootSectorStatus->iStatus);
+ aDi.iEncryptEndPos = bootSectorStatus->iEncryptEndPos;
+
+ // write to boot sector to indicate we are no longer finalised
+ WriteEncryptionStatusToBootSector(aDi, EFalse);
+
+ iBusy = ETrue;
+ }
+ else if (volumeChanged || aDi.Status() == ENfeUnmounted)
+ {
+ SetStatus(aDi, fatBootSectorStatus);
+ if (aDi.Status() == ENfeEncrypted)
+ {
+ aDi.iEncryptStartPos = aDi.iEntry.iPartitionBaseAddr;
+ aDi.iEncryptEndPos = aDi.iEntry.iPartitionBaseAddr + aDi.iEntry.iPartitionLen;
+ }
+ }
+ }
+
+
+TInt DMediaDriverNFE::WriteEncryptionStatusToBootSector(TNfeDriveInfo &aDi, TBool aFinalised)
+ {
+ if (!aDi.IsUDADrive())
+ return KErrNone;
+
+ if (aDi.iDriveFinalised == aFinalised)
+ return KErrNone;
+
+ TNfeDiskStatus status = aDi.Status();
+
+ TInt64 currentPos = aDi.iEntry.iPartitionBaseAddr;
+ TInt64 currentLen = KSectorSize;
+ TNfeDriveInfo* di = &aDi;
+ TBool encodeBuffer = EFalse;
+
+ if (status == ENfeEncrypting || status == ENfeEncrypted || status == ENfeDecrypting)
+ encodeBuffer = AdjustRequest(di, currentPos, currentLen);
+
+
+ TInt r = Read(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
+ if (r != KErrNone)
+ return r;
+ TPtr8 des(iBuffer, I64LOW(currentLen), I64LOW(currentLen));
+
+ if (encodeBuffer)
+ DecryptBuffer(des);
+
+
+ TBootSectorStatus* bootSectorStatus = (TBootSectorStatus*) iBuffer;
+
+ if (status == ENfeEncrypting || status == ENfeDecrypting)
+ {
+ bootSectorStatus->iSignature = TBootSectorStatus::ENfeBootSectorSignature;
+ bootSectorStatus->iEncryptEndPos = di->iEncryptEndPos;
+ bootSectorStatus->iStatus = status;
+ bootSectorStatus->iFinalised = aFinalised;
+ }
+ else
+ {
+ bootSectorStatus->iSignature = 0;
+ bootSectorStatus->iEncryptEndPos = 0;
+ bootSectorStatus->iStatus = ENfeUnmounted;
+ bootSectorStatus->iFinalised = EFalse;
+ }
+
+ if (encodeBuffer)
+ EncryptBuffer(des);
+
+
+ r = Write(di->iLocalDriveNum, di->iEntry.iPartitionBaseAddr, (TLinAddr) iBuffer, KSectorSize);
+ return r;
+ }
+
+
+/**
+HandleDiskContent -
+
+Called from Idle timer DFC
+
+Starts encrypting the current drive (iDrives[iDriveIndex]) from the current encryption position (iEncryptEndPos)
+*/
+TInt DMediaDriverNFE::HandleDiskContent()
+ {
+ TNfeDriveInfo* di = &iInfo.iDrives[iDriveIndex];
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d at pos %lx", iInstance, di->iLocalDriveNum, di->iEncryptEndPos));
+
+ if (di->iDriveFinalised)
+ {
+ __KTRACE_PRINT(Kern::Printf("HandleDiskContent aborting as drive has been finalised", iInstance));
+ return KErrNone;
+ }
+
+// TInt KBackgroundPriority = 7; //*test*
+// Kern::SetThreadPriority(KBackgroundPriority); //*test*
+
+ TInt r = KErrNone;
+ for (;;)
+ {
+ // If we've finished encryting this drive, change the state and move on to the next drive
+ if (r != KErrNone || di->iEncryptEndPos >= di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen)
+ {
+ if (di->Status() == ENfeEncrypting)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Finished encrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
+ SetStatus(*di, r == KErrNone ? ENfeEncrypted : ENfeCorrupted);
+ }
+ if (di->Status() == ENfeDecrypting)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Finished decrypting Drive %d r %d", iInstance, di->iLocalDriveNum, r));
+ SetStatus(*di, r == KErrNone ? ENfeDecrypted : ENfeCorrupted);
+ }
+
+ // write to boot sector to indicate we have finished encrypting/decrypting this drive
+ r = WriteEncryptionStatusToBootSector(*di);
+
+ di = NextDrive();
+ if (di == NULL)
+ {
+ r = KErrCompletion;
+ break;
+ }
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Starting to encrypt Drive %d", iInstance, iInfo.iDrives[iDriveIndex].iLocalDriveNum));
+ }
+
+ // If this media or any of the attached media are busy, stop encrypting & wait for the next idle timeout
+ if (MediaBusy(di->iLocalDriveNum))
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Media is busy !!!", iInstance));
+ r = KErrNone; // goto sleep & wait for another timer event
+ break;
+ }
+
+ TInt64& pos = di->iEncryptEndPos;
+ TInt64 partitionEnd = di->iEntry.iPartitionBaseAddr + di->iEntry.iPartitionLen;
+ TInt len = (TInt) Min (partitionEnd - pos, KBufSize);
+
+#if defined(TRACE_ENABLED)
+ // print position every 1/16 of the partition size
+ TInt64 printPos = Max((di->iEntry.iPartitionLen >> 4) & ~(KBufSize-1), KBufSize);
+ if (((di->iEncryptEndPos - di->iEncryptStartPos)% printPos) == 0)
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
+#endif
+// __KTRACE_PRINT(Kern::Printf("NFE%d: Encrypting drive %d from %lx to %lx end %lx", iInstance, di->iLocalDriveNum, pos, pos + len, partitionEnd));
+
+
+ // Read a buffer, encrypt it, and then write it back
+ // retry in case of media change
+ const TInt KRetries = 5;
+ r = KErrNotReady;
+ for (TInt i=0; r == KErrNotReady && i < KRetries; i++)
+ {
+ r = Read(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
+ if (r != KErrNone)
+ continue;
+
+ TPtr8 des(iBuffer,len,len);
+ if (di->Status() == ENfeEncrypting)
+ EncryptBuffer(des);
+ else
+ DecryptBuffer(des);
+
+ r = Write(di->iLocalDriveNum, pos, (TLinAddr) iBuffer, len);
+ }
+
+ if (r == KErrNone)
+ pos+= len;
+
+ if (di->iProgressToUiProperty) // no iProgressToUiProperty for swap drive
+ {
+ TInt progress = (TInt) (KNfeDiskOpReady * (pos - di->iEntry.iPartitionBaseAddr) / di->iEntry.iPartitionLen);
+// __KTRACE_PRINT(Kern::Printf("NFE%d: Progess %d ", progress));
+ ((RPropertyRef*) (di->iProgressToUiProperty))->Set( progress ); // Return value ignored
+ }
+ }
+
+ __KTRACE_PRINT(Kern::Printf("NFE%d: HandleDiskContent returned %d", iInstance, r));
+
+ // If not completed, start the idle timer & try again later
+ if (r != KErrCompletion)
+ iIdleTimer.OneShot(NKern::TimerTicks(KNotBusyInterval));
+
+// Kern::SetThreadPriority(KNfeThreadPriority); //*test*
+
+ return r;
+ }
+
+
+
+DECLARE_EXTENSION_PDD()
+ {
+ __KTRACE_PRINT(Kern::Printf("DECLARE_EXTENSION_PDD()"));
+ return new DPhysicalDeviceMediaNFE;
+ }
+
+DECLARE_STANDARD_EXTENSION()
+ {
+ __KTRACE_PRINT(Kern::Printf("DECLARE_STANDARD_EXTENSION()"));
+
+
+ // Create the media driver factory object and register this with the kernel
+ __KTRACE_PRINT(Kern::Printf("Creating NFE PDD"));
+ DPhysicalDeviceMediaNFE* device = new DPhysicalDeviceMediaNFE;
+ if (device == NULL)
+ return KErrNoMemory;
+ TInt r = Kern::InstallPhysicalDevice(device);
+ __KTRACE_PRINT(Kern::Printf("Installing NFE PDD in extension init - name %s r:%d", NFE_DRIVENAME, r));
+ if (r != KErrNone)
+ return r;
+
+ TInt swapInstance = KErrNotFound;
+#if defined (__DEMAND_PAGING__)
+ swapInstance = SwapInstance();
+#endif
+
+ DPrimaryMediaExt* primaryMedia[NFE_INSTANCE_COUNT];
+ TInt instance;
+
+ for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
+ {
+ // Register this media device & define which drives we want to attach to.
+ // These drives must already be registered with the local media subsystem
+ // i.e. this media's kernel extension must be defined AFTER any attached
+ // media's kernel extension in the appropriate .IBY file
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Creating NFE primary media", instance));
+ DPrimaryMediaExt* pM = new DPrimaryMediaExt(instance);
+ if (pM == NULL)
+ return KErrNoMemory;
+ primaryMedia[instance] = pM;
+
+ _LIT(KMediaThreadName,"NfeThread?");
+ HBuf* pMediaThreadName = HBuf::New(KMediaThreadName);
+ (*pMediaThreadName)[9] = (TUint8) ('0' + (TUint8) instance);
+
+ TInt r = Kern::DfcQInit(&pM->iNfeDfcQ,KNfeThreadPriority,pMediaThreadName);
+ if (r != KErrNone)
+ return r;
+
+#ifdef CPU_AFFINITY_ANY
+ NKern::ThreadSetCpuAffinity((NThread*)(pM->iNfeDfcQ.iThread), KCpuAffinityAny);
+#endif
+
+
+ pM->iDfcQ = &pM->iNfeDfcQ;
+ pM->iMsgQ.Receive();
+
+
+ const TInt* driveList = DriveList(instance);
+ TInt driveCount = DriveCount(instance);
+
+ TBuf<4> driveName(_L("NFE?"));
+ driveName[3] = (TUint8) ('0' + (TUint8) instance);
+
+
+ r = LocDrv::RegisterMediaDevice(
+ MEDIA_DEVICE_NFE,
+ driveCount, driveList,
+ pM, NFE_NUMMEDIA, driveName);
+ if (r != KErrNone)
+ return r;
+
+
+#if defined (__DEMAND_PAGING__)
+ if (PagingType(instance))
+ {
+ // Define which of the drives we have already attached to have code or data paging enabled
+ const TInt* pageDriveList = PageDriveList(instance);
+ TInt pageDriveCount = PageDriveCount(instance);
+
+ r = LocDrv::RegisterPagingDevice(pM,pageDriveList,pageDriveCount,PagingType(instance),SECTOR_SHIFT,NFE_NUM_PAGES);
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Installing NFE PagingDevice in extension init - r:%d", pM->iInstance, r));
+ // Ignore error if demand paging not supported by kernel
+ if (r == KErrNotSupported)
+ r = KErrNone;
+ if (r != KErrNone)
+ return r;
+ }
+
+
+#endif // __NAND_DEMAND_PAGING__
+
+ /*
+ If there is a swap partition we need to make sure all instances have their PartitionInfo() called
+ so that we can flag the swap partition as 'encrypted' if there are any encrypted drives at all
+ */
+ if (swapInstance != KErrNotFound)
+ {
+ TBuf8<sizeof(TLocalDriveCapsV6)> capsBuf;
+ capsBuf.SetMax();
+ capsBuf.FillZ();
+ DLocalDrive::Caps(driveList[0], capsBuf);
+ }
+ }
+
+
+ // If we encounter an encrypted drive belonging to ANY NFE instance, then assume the swap partition is
+ // encrypted too. We need to do this because the swap partition has no equivalent of the boot sector
+ if (swapInstance != KErrNotFound)
+ {
+ __KTRACE_PRINT(Kern::Printf("NFE: Searching for encrypted drives to determine whether swap partition should be encrypted..."));
+ TBool encryptedDriveFound = EFalse;
+ TNfeDriveInfo* swapDriveInfo = NULL;
+ for (instance=0; instance<NFE_INSTANCE_COUNT; instance++)
+ {
+ DPrimaryMediaExt* pM = primaryMedia[instance];
+ DMediaDriverNFE* mediaDriver = (DMediaDriverNFE*) pM->iDriver;
+ __ASSERT_ALWAYS(mediaDriver, NFE_FAULT());
+
+ if (swapDriveInfo == NULL)
+ swapDriveInfo = mediaDriver->GetSwapDrive();
+
+ for (TInt i=0; i<mediaDriver->iInfo.iDriveCount; i++)
+ {
+ TNfeDriveInfo& di = mediaDriver->iInfo.iDrives[i];
+ __KTRACE_PRINT(Kern::Printf("NFE%d: Testing drive %d DriveLetter %c status %s",
+ instance, di.iLocalDriveNum, (TInt) DriveLetterToAscii(di.iDriveLetter), DriveStatus(di.Status()) ));
+ if (di.Status() == ENfeEncrypted || di.Status() == ENfeEncrypting)
+ encryptedDriveFound = ETrue;
+ }
+ }
+ if (swapDriveInfo)
+ {
+ swapDriveInfo->SetStatus(encryptedDriveFound ? ENfeEncrypted : ENfeDecrypted);
+ swapDriveInfo->iEncryptEndPos = swapDriveInfo->iEntry.iPartitionBaseAddr + swapDriveInfo->iEntry.iPartitionLen;
+
+ __KTRACE_PRINT(Kern::Printf("NFE: Setting swap partition state to %s...", DriveStatus(swapDriveInfo->Status())));
+ }
+ }
+
+
+ return r;
+ }
+
+