# HG changeset patch # User hgs # Date 1272057631 -3600 # Node ID fc55edbf39194cbdb9af0c5296c41df869b71aa3 # Parent 70ba09fd07a5171ddee1d4aad0e04ff81eeeb539 201015_11 diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/bmarm/elocdu.def --- a/kernel/eka/bmarm/elocdu.def Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/bmarm/elocdu.def Fri Apr 23 22:20:31 2010 +0100 @@ -52,4 +52,19 @@ GetNextPhysicalAddress__14TLocDrvRequestRUlRi @ 51 NONAME R3UNUSED ; TLocDrvRequest::GetNextPhysicalAddress(unsigned long &, int &) RegisterDmaDevice__6LocDrvP17DPrimaryMediaBaseiii @ 52 NONAME ; LocDrv::RegisterDmaDevice(DPrimaryMediaBase *, int, int, int) ReadFromPageHandler__14TLocDrvRequestPvii @ 53 NONAME ; TLocDrvRequest::ReadFromPageHandler(void *, int, int) + __21DMediaDriverExtensioni @ 54 NONAME R3UNUSED ; DMediaDriverExtension::DMediaDriverExtension(int) + Close__21DMediaDriverExtension @ 55 NONAME R3UNUSED ; DMediaDriverExtension::Close(void) + DoDrivePartitionInfo__21DMediaDriverExtensionR14TPartitionInfo @ 56 NONAME R3UNUSED ; DMediaDriverExtension::DoDrivePartitionInfo(TPartitionInfo &) + ForwardRequest__21DMediaDriverExtensionR14TLocDrvRequest @ 57 NONAME R3UNUSED ; DMediaDriverExtension::ForwardRequest(TLocDrvRequest &) + MediaBusy__21DMediaDriverExtensioni @ 58 NONAME R3UNUSED ; DMediaDriverExtension::MediaBusy(int) + NotifyEmergencyPowerDown__21DMediaDriverExtension @ 59 NONAME R3UNUSED ; DMediaDriverExtension::NotifyEmergencyPowerDown(void) + NotifyPowerDown__21DMediaDriverExtension @ 60 NONAME R3UNUSED ; DMediaDriverExtension::NotifyPowerDown(void) + Read__21DMediaDriverExtensionixUlUi @ 61 NONAME ; DMediaDriverExtension::Read(int, long long, unsigned long, unsigned int) + Write__21DMediaDriverExtensionixUlUi @ 62 NONAME ; DMediaDriverExtension::Write(int, long long, unsigned long, unsigned int) + "_._21DMediaDriverExtension" @ 63 NONAME R3UNUSED ; DMediaDriverExtension::~DMediaDriverExtension(void) + Caps__21DMediaDriverExtensioniR5TDes8 @ 64 NONAME R3UNUSED ; DMediaDriverExtension::Caps(int, TDes8 &) + SetTotalSizeInBytes__12DMediaDriverR17TLocalDriveCapsV4 @ 65 NONAME R3UNUSED ; DMediaDriver::SetTotalSizeInBytes(TLocalDriveCapsV4 &) + ReadPaged__21DMediaDriverExtensionixUlUi @ 66 NONAME ; DMediaDriverExtension::ReadPaged(int, long long, unsigned long, unsigned int) + WritePaged__21DMediaDriverExtensionixUlUi @ 67 NONAME ; DMediaDriverExtension::WritePaged(int, long long, unsigned long, unsigned int) + Caps__11DLocalDriveiR5TDes8 @ 68 NONAME R3UNUSED ; DLocalDrive::Caps(int, TDes8 &) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/bwins/elocdu.def --- a/kernel/eka/bwins/elocdu.def Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/bwins/elocdu.def Fri Apr 23 22:20:31 2010 +0100 @@ -49,4 +49,17 @@ ?Set@TPartitionTableScanner@@QAEXPAEPAVTPartitionEntry@@H_J@Z @ 48 NONAME ; public: void __thiscall TPartitionTableScanner::Set(unsigned char *,class TPartitionEntry *,int,__int64) ?GetNextPhysicalAddress@TLocDrvRequest@@QAEHAAKAAH@Z @ 49 NONAME ; int TLocDrvRequest::GetNextPhysicalAddress(unsigned long &, int &) ?RegisterDmaDevice@LocDrv@@SAHPAVDPrimaryMediaBase@@HHH@Z @ 50 NONAME ; int LocDrv::RegisterDmaDevice(class DPrimaryMediaBase *, int, int, int) + ??0DMediaDriverExtension@@QAE@H@Z @ 51 NONAME ; public: __thiscall DMediaDriverExtension::DMediaDriverExtension(int) + ??1DMediaDriverExtension@@UAE@XZ @ 52 NONAME ; public: virtual __thiscall DMediaDriverExtension::~DMediaDriverExtension(void) + ?Caps@DMediaDriverExtension@@QAEHHAAVTDes8@@@Z @ 53 NONAME ; public: int __thiscall DMediaDriverExtension::Caps(int,class TDes8 &) + ?Close@DMediaDriverExtension@@UAEXXZ @ 54 NONAME ; public: virtual void __thiscall DMediaDriverExtension::Close(void) + ?DoDrivePartitionInfo@DMediaDriverExtension@@QAEHAAVTPartitionInfo@@@Z @ 55 NONAME ; public: int __thiscall DMediaDriverExtension::DoDrivePartitionInfo(class TPartitionInfo &) + ?ForwardRequest@DMediaDriverExtension@@QAEHAAVTLocDrvRequest@@@Z @ 56 NONAME ; public: int __thiscall DMediaDriverExtension::ForwardRequest(class TLocDrvRequest &) + ?MediaBusy@DMediaDriverExtension@@QAEHH@Z @ 57 NONAME ; public: int __thiscall DMediaDriverExtension::MediaBusy(int) + ?NotifyEmergencyPowerDown@DMediaDriverExtension@@UAEXXZ @ 58 NONAME ; public: virtual void __thiscall DMediaDriverExtension::NotifyEmergencyPowerDown(void) + ?NotifyPowerDown@DMediaDriverExtension@@UAEXXZ @ 59 NONAME ; public: virtual void __thiscall DMediaDriverExtension::NotifyPowerDown(void) + ?Read@DMediaDriverExtension@@QAEHH_JKI@Z @ 60 NONAME ; public: int __thiscall DMediaDriverExtension::Read(int,__int64,unsigned long,unsigned int) + ?SetTotalSizeInBytes@DMediaDriver@@QAEXAAVTLocalDriveCapsV4@@@Z @ 61 NONAME ; public: void __thiscall DMediaDriver::SetTotalSizeInBytes(class TLocalDriveCapsV4 &) + ?Write@DMediaDriverExtension@@QAEHH_JKI@Z @ 62 NONAME ; public: int __thiscall DMediaDriverExtension::Write(int,__int64,unsigned long,unsigned int) + ?Caps@DLocalDrive@@SAHHAAVTDes8@@@Z @ 63 NONAME ; public: static int __cdecl DLocalDrive::Caps(int,class TDes8 &) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/bx86/elocdu.def --- a/kernel/eka/bx86/elocdu.def Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/bx86/elocdu.def Fri Apr 23 22:20:31 2010 +0100 @@ -52,4 +52,19 @@ ?GetNextPhysicalAddress@TLocDrvRequest@@QAEHAAKAAH@Z @ 51 NONAME ; public: int __thiscall TLocDrvRequest::GetNextPhysicalAddress(unsigned long &,int &) ?RegisterDmaDevice@LocDrv@@SAHPAVDPrimaryMediaBase@@HHH@Z @ 52 NONAME ; public: static int __cdecl LocDrv::RegisterDmaDevice(class DPrimaryMediaBase *,int,int,int) ?ReadFromPageHandler@TLocDrvRequest@@QAEHPAXHH@Z @ 53 NONAME ; public: int __thiscall TLocDrvRequest::ReadFromPageHandler(void *,int,int) + ??0DMediaDriverExtension@@QAE@H@Z @ 54 NONAME ; public: __thiscall DMediaDriverExtension::DMediaDriverExtension(int) + ??1DMediaDriverExtension@@UAE@XZ @ 55 NONAME ; public: virtual __thiscall DMediaDriverExtension::~DMediaDriverExtension(void) + ?Caps@DMediaDriverExtension@@QAEHHAAVTDes8@@@Z @ 56 NONAME ; public: int __thiscall DMediaDriverExtension::Caps(int,class TDes8 &) + ?Close@DMediaDriverExtension@@UAEXXZ @ 57 NONAME ; public: virtual void __thiscall DMediaDriverExtension::Close(void) + ?DoDrivePartitionInfo@DMediaDriverExtension@@QAEHAAVTPartitionInfo@@@Z @ 58 NONAME ; public: int __thiscall DMediaDriverExtension::DoDrivePartitionInfo(class TPartitionInfo &) + ?ForwardRequest@DMediaDriverExtension@@QAEHAAVTLocDrvRequest@@@Z @ 59 NONAME ; public: int __thiscall DMediaDriverExtension::ForwardRequest(class TLocDrvRequest &) + ?MediaBusy@DMediaDriverExtension@@QAEHH@Z @ 60 NONAME ; public: int __thiscall DMediaDriverExtension::MediaBusy(int) + ?NotifyEmergencyPowerDown@DMediaDriverExtension@@UAEXXZ @ 61 NONAME ; public: virtual void __thiscall DMediaDriverExtension::NotifyEmergencyPowerDown(void) + ?NotifyPowerDown@DMediaDriverExtension@@UAEXXZ @ 62 NONAME ; public: virtual void __thiscall DMediaDriverExtension::NotifyPowerDown(void) + ?Read@DMediaDriverExtension@@QAEHH_JKI@Z @ 63 NONAME ; public: int __thiscall DMediaDriverExtension::Read(int,__int64,unsigned long,unsigned int) + ?Write@DMediaDriverExtension@@QAEHH_JKI@Z @ 64 NONAME ; public: int __thiscall DMediaDriverExtension::Write(int,__int64,unsigned long,unsigned int) + ?SetTotalSizeInBytes@DMediaDriver@@QAEXAAVTLocalDriveCapsV4@@@Z @ 65 NONAME ; public: void __thiscall DMediaDriver::SetTotalSizeInBytes(class TLocalDriveCapsV4 &) + ?ReadPaged@DMediaDriverExtension@@QAEHH_JKI@Z @ 66 NONAME ; public: int __thiscall DMediaDriverExtension::ReadPaged(int,__int64,unsigned long,unsigned int) + ?WritePaged@DMediaDriverExtension@@QAEHH_JKI@Z @ 67 NONAME ; public: int __thiscall DMediaDriverExtension::WritePaged(int,__int64,unsigned long,unsigned int) + ?Caps@DLocalDrive@@SAHHAAVTDes8@@@Z @ 68 NONAME ; public: static int __cdecl DLocalDrive::Caps(int,class TDes8 &) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/locmedia/dmasupport.cpp --- a/kernel/eka/drivers/locmedia/dmasupport.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/locmedia/dmasupport.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -278,7 +278,7 @@ TInt r; do { - __KTRACE_DMA(Kern::Printf(">PHYSADDR:SendReceive() iReqLen %d; iLenConsumed %d; fragments %d",iReqLen, iLenConsumed, fragments)); + __KTRACE_DMA(Kern::Printf(">PHYSADDR:SendReceive() iReqLen %d; iLenConsumed %d; fragments %d",iReqLenClient, iLenConsumed, fragments)); OstTraceExt2( TRACE_DMASUPPORT, DDMAHELPER_SENDRECEIVE1, "PHYSADDR:SendReceive() iLenConsumed=%d; fragments=%d", iLenConsumed, fragments); r = RequestStart(); if (r != KErrNone) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/locmedia/locmedia.cpp --- a/kernel/eka/drivers/locmedia/locmedia.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/locmedia/locmedia.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -71,6 +71,9 @@ class DPrimaryMediaBase::DBody : public DBase { public: + DBody(DPrimaryMediaBase& aPrimaryMediaBase); +public: + DPrimaryMediaBase& iPrimaryMediaBase; // ptr to parent TInt iPhysDevIndex; TInt iRequestCount; #ifdef __DEMAND_PAGING__ @@ -78,12 +81,24 @@ TInt iPageSizeMsk; // Mask of page size (e.g. 4096-1 -> 4095) TInt iMediaChanges; #endif + + // This bit mask indicates which local drives the media is attached to + TUint32 iRegisteredDriveMask; + + // Set to ETrue for media extension drivers + TBool iMediaExtension; + + // Media change DFCs to allow media change events from attached media + // to be handled in the context of an extension media's thread + TDfc iMediaChangeDfc; + TDfc iMediaPresentDfc; }; #ifdef __DEMAND_PAGING__ DMediaPagingDevice* ThePagingDevices[KMaxLocalDrives]; DPrimaryMediaBase* TheRomPagingMedia = NULL; DPrimaryMediaBase* TheDataPagingMedia = NULL; +TLocDrv* TheDataPagingDrive = NULL; TBool DataPagingDeviceRegistered = EFalse; class DPinObjectAllocator; DPinObjectAllocator* ThePinObjectAllocator = NULL; @@ -92,10 +107,29 @@ // In this case, we need to avoid taking page faults on the non-paging media too, hence the need for these checks: inline TBool DataPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia) {return TheDataPagingMedia && TheDataPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;} + + +TBool DataPagingMedia(DPrimaryMediaBase* aPrimaryMedia) + { + for (TLocDrv* drv = TheDataPagingDrive; drv; drv = drv->iNextDrive) + if (drv->iPrimaryMedia == aPrimaryMedia) + return ETrue; + return EFalse; + } + inline TBool RomPagingDfcQ(DPrimaryMediaBase* aPrimaryMedia) {return TheRomPagingMedia && TheRomPagingMedia->iDfcQ == aPrimaryMedia->iDfcQ;} +#if defined(_DEBUG) + #define SETDEBUGFLAG(aBitNum) {Kern::SuperPage().iDebugMask[aBitNum >> 5] |= (1 << (aBitNum & 31));} + #define CLRDEBUGFLAG(aBitNum) {Kern::SuperPage().iDebugMask[aBitNum >> 5] &= ~(1 << (aBitNum & 31));} +#else + #define SETDEBUGFLAG(aBitNum) + #define CLRDEBUGFLAG(aBitNum) +#endif + + /* DPinObjectAllocator @@ -104,6 +138,7 @@ (1) a queue of pre-allocated TVirtualPinObject's; (2) a single pre-allocated DFragmentationPagingLock object: this may be used if there are no TVirtualPinObject's available or if Kern::PinVirtualMemory() fails +@internalTechnology */ NONSHARABLE_CLASS(DPinObjectAllocator) : public DBase { @@ -157,7 +192,7 @@ delete iPreAllocatedDataLock; } - for (TInt n=0; niNextDrive) + { + iDrive = iDrive->iNextDrive; + return iDrive; + } + iIndex++; + } + + for (iDrive = NULL; iIndex < KMaxLocalDrives; iIndex++) + { + iDrive = TheDrives[iIndex]; + if (iDrive) + break; + } + + return iDrive; + } + +/* +Returns the first TLocDrv in the chain of attached drives which matches DPrimaryMediaBase +*/ +TLocDrv* TDriveIterator::GetDrive(TInt aDriveNum, DPrimaryMediaBase* aPrimaryMedia) + { + TLocDrv* drive = TheDrives[aDriveNum]; + while (drive && drive->iPrimaryMedia != aPrimaryMedia) + { + drive = drive->iNextDrive ? drive->iNextDrive : NULL; + } + return drive; + } + +/* +Returns the last TLocDrv in the chain of attached drives - +i.e. the TLocDrv attached to physical media rather than a TLocDrv corresponding to a media extension +*/ +TLocDrv* TDriveIterator::GetPhysicalDrive(TLocDrv* aDrv) + { + __ASSERT_DEBUG(aDrv, LOCM_FAULT()); + while (aDrv->iNextDrive) + aDrv = aDrv->iNextDrive; + return aDrv; + } + +#if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__) +DMediaPagingDevice* TDriveIterator::PagingDevice(TInt aDriveNum, DPagingDevice::TType aType) + { + TLocDrv* drive = TheDrives[aDriveNum]; + DMediaPagingDevice* pagingDevice = drive ? drive->iPrimaryMedia->iBody->iPagingDevice : NULL; + while (drive && (pagingDevice == NULL || (pagingDevice->iType & aType) == 0)) + { + drive = drive->iNextDrive ? drive->iNextDrive : NULL; + pagingDevice = drive ? drive->iPrimaryMedia->iBody->iPagingDevice : NULL; + } + return pagingDevice; + } +#endif + /******************************************** * Local drive device base class ********************************************/ @@ -312,7 +439,8 @@ /******************************************** * Local drive interface class ********************************************/ -DLocalDrive::DLocalDrive() +DLocalDrive::DLocalDrive() : + iMediaChangeObserver(MediaChangeCallback, this, TCallBackLink::EDLocalDriveObject) { // iLink.iNext=NULL; } @@ -489,42 +617,6 @@ m.Length()=KMaxLocalDriveCapsLength; // for pinning r=iDrive->Request(m); - if(r == KErrNone && iDrive->iMedia != NULL && iDrive->iMedia->iDriver != NULL) - { - // Fill in default media size if not specified by the driver - // - // - This uses the members of TLocalDriveCapsV4 which was primarily used - // to report NAND flash characteristics, but are general enough to be - // used to report the size of any type of media without adding yet - // another extension to TLocalDriveCapsVx. - // - - TLocalDriveCapsV4& caps = *(TLocalDriveCapsV4*)capsBuf.Ptr(); - - if(caps.iSectorSizeInBytes == 0) - { - // Fill in a default value for the disk sector size - caps.iSectorSizeInBytes = 512; - - // Zero the number of sectors, as a sector count makes no sense without a sector size - // - Fault in debug mode if a sector count is provided to ensure that media driver creators - // set this value,but in release mode continue gracefully be recalculating the sector count. - __ASSERT_DEBUG(caps.iNumberOfSectors == 0, LOCM_FAULT()); - caps.iNumberOfSectors = 0; - caps.iNumPagesPerBlock = 1; // ...to ensure compatiility with NAND semantics - } - - if(caps.iNumberOfSectors == 0) - { - const Int64 totalSizeInSectors = iDrive->iMedia->iDriver->TotalSizeInBytes() / caps.iSectorSizeInBytes; - __ASSERT_DEBUG(I64HIGH(totalSizeInSectors) == 0, LOCM_FAULT()); - - if(I64HIGH(totalSizeInSectors) == 0) - { - caps.iNumberOfSectors = I64LOW(totalSizeInSectors); - } - } - } #if defined(OST_TRACE_COMPILER_IN_USE) && defined(_DEBUG) const TLocalDriveCapsV5& caps=*(const TLocalDriveCapsV5*)capsBuf.Ptr(); @@ -593,7 +685,11 @@ { OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLISREMOVABLE, "EControlIsRemovable; TLocDrvRequest Object=0x%x", (TUint) &m); TInt sockNum; - r=iDrive->iPrimaryMedia->IsRemovableDevice(sockNum); + + // Pass request on to last chained drive + TLocDrv* drv = TDriveIterator::GetPhysicalDrive(iDrive); + r = drv->iPrimaryMedia->IsRemovableDevice(sockNum); + if (r) kumemput32(a1,&sockNum,sizeof(TInt)); break; @@ -636,7 +732,11 @@ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_CONTROLSETMOUNTINFO, "EControlSetMountInfo; TLocDrvRequest Object=0x%x", (TUint) &m); m.Id()=ERead; r=m.ProcessMessageData(a1); - DPrimaryMediaBase* pM=iDrive->iPrimaryMedia; + + // Pass request on to last chained drive + TLocDrv* drv = TDriveIterator::GetPhysicalDrive(iDrive); + DPrimaryMediaBase* pM = drv->iPrimaryMedia; + if(!pM || r!=KErrNone) break; @@ -874,11 +974,15 @@ TBuf8 queryBuf; queryBuf.SetMax(); queryBuf.FillZ(); - + + DThread* pT = m.Client(); + r = Kern::ThreadDesRead(pT, (TDes8*)a2, queryBuf, 0 ,KChunkShiftBy0); + + queryBuf.SetMax(); m.Id() = EQueryDevice; - m.iArg[0] = a1; // RLocalDrive::TQueryDevice + m.iArg[0] = a1; // RLocalDrive::TQueryDevice m.RemoteDes() = (TAny*)queryBuf.Ptr(); // overload this - m.Length() = KMaxLocalDriveCapsLength; // for pinning + m.Length() = KMaxQueryDeviceLength; OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE, "EQueryDevice; TLocDrvRequest Object=0x%x", (TUint) &m); r=iDrive->Request(m); OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_REQUEST, DLOCALDRIVE_REQUEST_QUERYDEVICE_RETURN, "EQueryDevice Return; TLocDrvRequest Object=0x%x", (TUint) &m); @@ -1033,7 +1137,7 @@ OstTrace1(TRACE_FLOW, DLOCALDRIVE_UNLOCKMOUNTINFO_ENTRY, "> DLocalDrive::UnlockMountInfo;aPrimaryMedia=%x", (TUint) &aPrimaryMedia); DMediaPagingDevice* pagingDevice = aPrimaryMedia.iBody->iPagingDevice; - if (pagingDevice == NULL || pagingDevice->iMountInfoDataLock == NULL) + if (pagingDevice == NULL) { OstTraceFunctionExit1( DLOCALDRIVE_UNLOCKMOUNTINFO_EXIT1, this ); return; @@ -1065,50 +1169,52 @@ } #endif // __DEMAND_PAGING__ -void DLocalDrive::NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange) +void DLocalDrive::NotifyChange() { - OstTraceExt2( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange;aPrimaryMedia=%x;aMediaChange=%d", (TUint) &aPrimaryMedia, aMediaChange ); -#ifndef __DEMAND_PAGING__ - aPrimaryMedia; -#endif - - // Complete any notification request on media change or power down - if (aMediaChange) + OstTrace0( TRACE_FLOW, DLOCALDRIVE_NOTIFYCHANGE_ENTRY, "> DLocalDrive::NotifyChange"); + + + // Complete any notification request on media change + DThread* pC=NULL; + NKern::LockSystem(); + if (iCleanup.iThread) { - DThread* pC=NULL; - NKern::LockSystem(); - if (iCleanup.iThread) - { - pC=iCleanup.iThread; - pC->Open(); - } - NKern::UnlockSystem(); - if (pC) + pC=iCleanup.iThread; + pC->Open(); + } + NKern::UnlockSystem(); + if (pC) + { + TBool b = ETrue; + // if change not yet queued, queue it now + if (iNotifyChangeRequest->IsReady()) { - TBool b = ETrue; - // if change not yet queued, queue it now - if (iNotifyChangeRequest->IsReady()) - { - *((TBool*) iNotifyChangeRequest->Buffer()) = b; - Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone); - } - // If change has not even been requested by the client, maintain the pre-wdp behaviour - // and write data immediately back to client (possibly taking a page fault) - // N.B. Must NOT do this on data paging media + *((TBool*) iNotifyChangeRequest->Buffer()) = b; + Kern::QueueRequestComplete(pC,iNotifyChangeRequest,KErrNone); + } + // If change has not even been requested by the client, maintain the pre-wdp behaviour + // and write data immediately back to client (possibly taking a page fault) + // N.B. Must NOT do this on data paging media #ifdef __DEMAND_PAGING__ - else if (!DataPagingDfcQ(&aPrimaryMedia)) + else if (!DataPagingDfcQ(iDrive->iPrimaryMedia)) #else - else + else #endif - { - Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL); - } - pC->AsyncClose(); + { + Kern::ThreadRawWrite(pC, iNotifyChangeRequest->DestPtr(), &b, sizeof(b), NULL); } + pC->AsyncClose(); } OstTraceFunctionExit1( DLOCALDRIVE_NOTIFYCHANGE_EXIT, this ); } +// This function is called by the primary media when a media change occurs +TInt DLocalDrive::MediaChangeCallback(TAny* aLocalDrive, TInt /* aNotifyType*/) + { + ((DLocalDrive*) aLocalDrive)->NotifyChange(); + return KErrNone; + } + TLocalDriveCleanup::TLocalDriveCleanup() { } @@ -1127,6 +1233,33 @@ NKern::LockSystem(); } + +EXPORT_C TInt DLocalDrive::Caps(TInt aDriveNumber, TDes8& aCaps) + { + if(!Kern::CurrentThreadHasCapability(ECapabilityTCB,__PLATSEC_DIAGNOSTIC_STRING("Checked by ELOCD.LDD (Local Media Driver)"))) + { + return KErrPermissionDenied; + } + + + if (aDriveNumber >= KMaxLocalDrives) + return KErrArgument; + + TLocDrv* drive = TheDrives[aDriveNumber]; + if (!drive) + return KErrNotSupported; + + TLocDrvRequest request; + memclr(&request, sizeof(request)); + + request.Drive() = drive; + request.Id() = DLocalDrive::ECaps; + request.Length() = aCaps.Length(); + request.RemoteDes() = (TAny*) aCaps.Ptr(); + + return request.SendReceive(&drive->iPrimaryMedia->iMsgQ); + } + /******************************************** * Local drive request class ********************************************/ @@ -1155,6 +1288,14 @@ { OstTraceFunctionEntry1( TLOCDRVREQUEST_READREMOTE_ENTRY, this ); TInt r; + + if (Flags() & TLocDrvRequest::EKernelBuffer) + { + (void)memcpy((TAny*) aDes->Ptr(), (TAny*)((TUint32)RemoteDes()+anOffset), aDes->MaxLength()); + aDes->SetLength(aDes->MaxLength()); + return KErrNone; + } + DThread* pT=RemoteThread(); if (!pT) pT=Client(); @@ -1294,6 +1435,14 @@ { OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITEREMOTE_ENTRY, this ); TInt r; + + if (Flags() & TLocDrvRequest::EKernelBuffer) + { + (void)memcpy((TAny*)((TUint32)RemoteDes()+anOffset), (TAny*) aDes->Ptr(), aDes->Length()); + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, KErrNone ); + return KErrNone; + } + DThread* pC=Client(); DThread* pT=RemoteThread(); if (!pT) @@ -1303,12 +1452,12 @@ if (Flags() & ETClientBuffer) { r = Kern::ThreadBufWrite(pT, (TClientBuffer*) RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC); - OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT1, this, r ); + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r ); return r; } #endif r = Kern::ThreadDesWrite(pT,RemoteDes(),*aDes,anOffset+RemoteDesOffset(),KChunkShiftBy0,pC); - OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT2, this, r ); + OstTraceFunctionExitExt( TLOCDRVREQUEST_WRITEREMOTE_EXIT3, this, r ); return r; } @@ -1489,7 +1638,7 @@ OstTraceExt2( TRACE_INTERNALS, TLOCDRVREQUEST_CHECKANDADJUSTFORPARTITION6, "Read/Write request length=0x%x; position=0x%x", (TUint) Length(), (TUint) Pos() ); if (DriverFlags() & RLocalDrive::ELocDrvWholeMedia) { - if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iDriver->iTotalSizeInBytes) + if (d.iMedia && d.iMedia->iDriver && Pos()+Length() > d.iMedia->iPartitionInfo.iMediaSizeInBytes) { r = KErrArgument; break; @@ -1519,9 +1668,22 @@ memclr(this, sizeof(TLocDrv)); iDriveNumber=aDriveNumber; iPartitionNumber=-1; + iMediaChangeObserver.iFunction = MediaChangeCallback; + iMediaChangeObserver.iPtr= this; + iMediaChangeObserver.iObjectType = TCallBackLink::ETLocDrvObject; OstTraceFunctionExit1( TLOCDRV_TLOCDRV_EXIT, this ); } +TInt TLocDrv::MediaChangeCallback(TAny* aLocDrv, TInt aNotifyType) + { + __ASSERT_DEBUG(aNotifyType == DPrimaryMediaBase::EMediaChange || aNotifyType == DPrimaryMediaBase::EMediaPresent, LOCM_FAULT()); + if (aNotifyType == DPrimaryMediaBase::EMediaPresent) + return ((TLocDrv*) aLocDrv)->iPrimaryMedia->iBody->iMediaPresentDfc.Enque(); + else + return ((TLocDrv*) aLocDrv)->iPrimaryMedia->iBody->iMediaChangeDfc.Enque(); + } + + /** Initialises the DMedia entity with the media device number and ID. @@ -1588,6 +1750,26 @@ OstTraceFunctionExit0( _HANDLEMSG_EXIT ); } + +void mediaChangeDfc(TAny* aPtr) + { + DPrimaryMediaBase* pM = (DPrimaryMediaBase*)aPtr; + pM->NotifyMediaChange(); + } + +void mediaPresentDfc(TAny* aPtr) + { + DPrimaryMediaBase* pM = (DPrimaryMediaBase*)aPtr; + pM->NotifyMediaPresent(); + } + +DPrimaryMediaBase::DBody::DBody(DPrimaryMediaBase& aPrimaryMediaBase) : + iPrimaryMediaBase(aPrimaryMediaBase), + iMediaChangeDfc(mediaChangeDfc, &aPrimaryMediaBase, KMaxDfcPriority), + iMediaPresentDfc(mediaPresentDfc, &aPrimaryMediaBase, KMaxDfcPriority) + { + } + EXPORT_C DPrimaryMediaBase::DPrimaryMediaBase() : iMsgQ(handleMsg, this, NULL, 1), iDeferred(NULL, NULL, NULL, 0), // callback never used @@ -1627,15 +1809,18 @@ { OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT1, this, r ); return r; - } - iBody = new DBody; + } + iBody = new DBody(*this); if (iBody == NULL) { OstTraceFunctionExitExt( DPRIMARYMEDIABASE_CREATE_EXIT2, this, KErrNoMemory ); return KErrNoMemory; - } - - + } + if (iDfcQ) + { + iBody->iMediaChangeDfc.SetDfcQ(iDfcQ); + iBody->iMediaPresentDfc.SetDfcQ(iDfcQ); + } #ifdef __DEMAND_PAGING__ TInt pageSize = Kern::RoundToPageSize(1); @@ -1697,7 +1882,7 @@ NKern::LockSystem(); TBool first=iConnectionQ.IsEmpty(); - iConnectionQ.Add(&aLocalDrive->iLink); + iConnectionQ.Add(&aLocalDrive->iMediaChangeObserver.iLink); NKern::UnlockSystem(); if (first) { @@ -1765,6 +1950,52 @@ OstTraceFunctionExit1( DPRIMARYMEDIABASE_DISCONNECT_EXIT2, this ); } + +/** +Connects a TLocDrv containing a media extension to the next primary media in the chain +*/ +TInt DPrimaryMediaBase::Connect(TLocDrv* aLocDrv) + { + TInt r = KErrNone; + + NKern::LockSystem(); + TBool first = iConnectionQ.IsEmpty(); + iConnectionQ.Add(&aLocDrv->iMediaChangeObserver.iLink); + NKern::UnlockSystem(); + + if (first && !iDfcQ) + { + r = OpenMediaDriver(); + if (r!=KErrNone) + { + NKern::LockSystem(); + aLocDrv->iMediaChangeObserver.iLink.Deque(); + NKern::UnlockSystem(); + } + } + return r; + } + +TInt DPrimaryMediaBase::HandleMediaNotPresent(TLocDrvRequest& aReq) + { + TInt reqId = aReq.Id(); + + if (reqId == DLocalDrive::ECaps) + DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes()); // fill in stuff we know even if no media present + + TInt r = QuickCheckStatus(); + if (r != KErrNone && + reqId != DLocalDrive::EForceMediaChange && // EForceMediaChange, and + reqId != DLocalDrive::EReadPasswordStore && // Password store operations + reqId != DLocalDrive::EWritePasswordStore && // do not require the media + reqId != DLocalDrive::EPasswordStoreLengthInBytes) // to be ready.) + { + return r; + } + + return KErrNone; + } + EXPORT_C TInt DPrimaryMediaBase::Request(TLocDrvRequest& aReq) /** Issues a local drive request. It is called from TLocDrv::Request() function . @@ -1785,7 +2016,7 @@ @see TLocDrvRequest */ { -OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this ); + OstTraceFunctionEntry1( DPRIMARYMEDIABASE_REQUEST_ENTRY, this ); __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::Request(%08x)",iMediaId,&aReq)); __KTRACE_OPT(KLOCDRV,Kern::Printf("this=%x, ReqId=%d, Pos=%lx, Len=%lx, remote thread %O",this,aReq.Id(),aReq.Pos(),aReq.Length(),aReq.RemoteThread())); @@ -1794,18 +2025,13 @@ TInt reqId = aReq.Id(); - if (reqId == DLocalDrive::ECaps) - DefaultDriveCaps(*(TLocalDriveCapsV2*)aReq.RemoteDes()); // fill in stuff we know even if no media present - - TInt r = QuickCheckStatus(); - if (r != KErrNone && aReq.Id()!=DLocalDrive::EForceMediaChange && // EForceMediaChange, and - aReq.Id()!=DLocalDrive::EReadPasswordStore && // Password store operations - aReq.Id()!=DLocalDrive::EWritePasswordStore && // do not require the media - aReq.Id()!=DLocalDrive::EPasswordStoreLengthInBytes) // to be ready.) - { + TInt r = HandleMediaNotPresent(aReq); + if (r != KErrNone) + { OstTraceFunctionExitExt( DPRIMARYMEDIABASE_REQUEST_EXIT, this, r ); return r; - } + } + // for ERead & EWrite requests, get the linear address for pinning & DMA @@ -2250,7 +2476,7 @@ case EConnect: { DLocalDrive* pD=(DLocalDrive*)m.Ptr0(); - iConnectionQ.Add(&pD->iLink); + iConnectionQ.Add(&pD->iMediaChangeObserver.iLink); m.Complete(KErrNone, EFalse); OstTraceFunctionExit1( DPRIMARYMEDIABASE_HANDLEMSG_EXIT1, this ); return; @@ -2274,6 +2500,22 @@ { TUint flags = (TUint) m.Pos(); + // For media extension drivers, send a copy of the request to the next drive in the chain and wait for it. + TLocDrv* drv = m.Drive(); + if (drv->iNextDrive) + { + TLocDrvRequest request; + request.Drive() = drv->iNextDrive; + request.Id() = DLocalDrive::EForceMediaChange; + request.Pos() = m.Pos(); // flags + + request.SendReceive(&drv->iNextDrive->iPrimaryMedia->iMsgQ); + + CompleteRequest(m, request.iValue); + return; + } + + // if KForceMediaChangeReOpenDriver specified wait for power up, // and then re-open this drive's media driver __KTRACE_OPT(KLOCDRV, Kern::Printf("EForceMediaChange, flags %08X\n", flags)); @@ -2504,18 +2746,18 @@ if (m.iValue == DLocalDrive::EForceMediaChange) { __ASSERT_DEBUG(((TUint) m.Pos()) == (TUint) KForceMediaChangeReOpenMediaDriver, LOCM_FAULT()); - iCurrentReq=NULL; TLocDrv* pL = m.Drive(); DMedia* media = pL->iMedia; + if (media && media->iDriver) CloseMediaDrivers(media); iState=EOpening; StartOpenMediaDrivers(); - NotifyClients(ETrue,pL); + NotifyClients(EMediaChange, pL); CompleteRequest(m, r); OstTraceFunctionExitExt( DPRIMARYMEDIABASE_DOREQUEST_EXIT, this, r ); return r; @@ -2542,7 +2784,7 @@ if (!(m.Flags() & TLocDrvRequest::EAdjusted)) { // If this isn't the only partition, don't allow access to the whole media - if (iTotalPartitionsOpened > 1) + if (TDriveIterator::GetPhysicalDrive(m.Drive())->iPrimaryMedia->iTotalPartitionsOpened > 1) m.DriverFlags() &= ~RLocalDrive::ELocDrvWholeMedia; r=m.CheckAndAdjustForPartition(); } @@ -2686,7 +2928,7 @@ // we mustn't ever close the media driver if it's responsible for data paging as re-opening the drive // would involve memory allocation which might cause deadlock if the kernel heap were to grow #ifdef __DEMAND_PAGING__ - if (DataPagingDfcQ(this)) + if (DataPagingMedia(this)) { __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for data paging media %08X", this)); OstTrace1(TRACE_FLOW, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS_EXIT1, "CloseMediaDrivers aborting for data paging media 0x%08x", this); @@ -2694,21 +2936,30 @@ } #endif - TInt i; - for (i=0; iiMediaExtension) { - TLocDrv* pL=TheDrives[i]; + __KTRACE_OPT(KLOCDRV,Kern::Printf("CloseMediaDrivers aborting for extension media %08X", this)); + return; + } + + + TDriveIterator driveIter; + for (TLocDrv* pL = driveIter.NextDrive(); pL != NULL; pL = driveIter.NextDrive()) + { if (pL && pL->iPrimaryMedia==this) { - __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",i)); - OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", i ); + __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d",driveIter.Index())); + OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_CLOSEMEDIADRIVERS2, "Drive=%d", driveIter.Index()); if (aMedia == NULL || pL->iMedia == aMedia) { pL->iMedia=NULL; } } } - for (i=iLastMediaId; i>=iMediaId; i--) + for (TInt i=iLastMediaId; i>=iMediaId; i--) { DMedia* pM=TheMedia[i]; if (aMedia == NULL || pM == aMedia) @@ -2865,7 +3116,7 @@ if (pM->iDriver) { #ifdef __DEMAND_PAGING__ - if (DataPagingDfcQ(this)) + if (DataPagingMedia(this)) { __KTRACE_OPT(KLOCDRV,Kern::Printf("DoPartitionInfoComplete(%d) Close Media Driver aborted for data paging media %08X", this)); OstTraceDef1(OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE2, "Close Media Driver for data paging media 0x%08x", this); @@ -2931,10 +3182,10 @@ TInt id=iMediaId; // start with primary media TInt partitionsOnThisMedia=PartitionCount(); TInt partition=0; - TInt j; - for (j=0; jiPrimaryMedia==this) { if (totalPartitions==0) @@ -2948,9 +3199,8 @@ partition=0; partitionsOnThisMedia=TheMedia[id]->PartitionCount(); } - __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",j,id,partition)); - OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", j, id, partition ); - + __KTRACE_OPT(KLOCDRV,Kern::Printf("Drive %d = Media %d Partition %d",driveIter.Index(),id,partition)); + OstTraceExt3( TRACE_INTERNALS, DPRIMARYMEDIABASE_DOPARTITIONINFOCOMPLETE5, "Local Drive=%d; iMediaId=%d; partition=%d", driveIter.Index(), id, partition ); pD->iMedia=TheMedia[id]; pD->iPartitionNumber=partition; memcpy(pD, pD->iMedia->iPartitionInfo.iEntry+partition, sizeof(TPartitionEntry)); @@ -3216,10 +3466,10 @@ OstTraceFunctionExit1( DPRIMARYMEDIABASE_SETCLOSED_EXIT, this ); } -void DPrimaryMediaBase::NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv) +void DPrimaryMediaBase::NotifyClients(TNotifyType aNotifyType, TLocDrv* aLocDrv) // -// Notify all clients of a media change or power-down event +// Notify all clients of a media change or media present event // { OstTraceFunctionEntryExt( DPRIMARYMEDIABASE_NOTIFYCLIENTS_ENTRY, this ); @@ -3227,11 +3477,23 @@ SDblQueLink* pL=iConnectionQ.iA.iNext; while (pL!=&iConnectionQ.iA) { - DLocalDrive* pD=_LOFF(pL,DLocalDrive,iLink); + // Get pointer to TCallBackLink + TCallBackLink* pCallBackLink = _LOFF(pL,TCallBackLink,iLink); + + // The link is embedded in either a TLocDrv or a DLocalDrive object; + // find out which one it is and then get TLocDrv pointer from that + __ASSERT_DEBUG(pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject || pCallBackLink->iObjectType == TCallBackLink::ETLocDrvObject, LOCM_FAULT()); + TLocDrv* locDrv; + if (pCallBackLink->iObjectType == TCallBackLink::EDLocalDriveObject) + locDrv = ((DLocalDrive*) _LOFF(pCallBackLink,DLocalDrive, iMediaChangeObserver))->iDrive; + else + locDrv = ((TLocDrv*) _LOFF(pCallBackLink,TLocDrv, iMediaChangeObserver))->iNextDrive; + // Issue the notification if the caller wants to notify all drives (aLocDrv == NULL) or // the specified drive matches this one - if (aLocDrv == NULL || aLocDrv == pD->iDrive) - pD->NotifyChange(*this, aMediaChange); + if (aLocDrv == NULL || aLocDrv == locDrv) + pCallBackLink->CallBack(aNotifyType); + pL=pL->iNext; } OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYCLIENTS_EXIT, this ); @@ -3249,32 +3511,13 @@ OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_MEDIACHANGE, DPRIMARYMEDIABASE_NOTIFYMEDIACHANGE, "iMediaId=%d; iState=%d", iMediaId, iState ); - TInt state=iState; - - __ASSERT_DEBUG(iBody, LOCM_FAULT()); - -#ifdef __DEMAND_PAGING__ - iBody->iMediaChanges++; - - // As data paging media never close, need to ensure the media driver cancels - // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange(). - // DMediaDriver::NotifyPowerDown() should do this - if(DataPagingDfcQ(this)) - NotifyPowerDown(); -#endif - - // complete any outstanding requests with KErrNotReady - // and any force media change requests with KErrNone - SetClosed(KErrNotReady); - - // close all media drivers on this device - if (state>=EOpening) - { - CloseMediaDrivers(); - } + // This should only be called in the context of the media thread + __ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT()); + + MediaChange(); // notify all connections that media change has occurred - NotifyClients(ETrue); + NotifyClients(EMediaChange); // complete any force media change requests iWaitMedChg.CompleteAll(KErrNone); @@ -3343,8 +3586,6 @@ CloseMediaDrivers(); SetClosed(KErrNotReady); } - - NotifyClients(EFalse); OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYPOWERDOWN_EXIT, this ); } @@ -3414,17 +3655,56 @@ } CloseMediaDrivers(); SetClosed(KErrNotReady); - NotifyClients(EFalse); OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYEMERGENCYPOWERDOWN_EXIT, this ); } + +/** +Called by NotifyMediaPresent() and NotifyMediaChange() to ensure the media is in the correct state +*/ +void DPrimaryMediaBase::MediaChange() + { + // Media has been inserted, so we need to cancel any outstanding requests and + // ensure that the partition info is read again + TInt state = iState; + + __ASSERT_DEBUG(iBody, LOCM_FAULT()); + +#ifdef __DEMAND_PAGING__ + iBody->iMediaChanges++; + + // As data paging media never close, need to ensure the media driver cancels + // any requests it owns as the stack may be powered down by DPBusPrimaryMedia::ForceMediaChange(). + // DMediaDriver::NotifyPowerDown() should do this + if (DataPagingMedia(this)) + NotifyPowerDown(); +#endif + + // complete any outstanding requests with KErrNotReady + // and any force media change requests with KErrNone + SetClosed(KErrNotReady); + + // close all media drivers on this device + if (state>=EOpening) + { + CloseMediaDrivers(); + } + } + EXPORT_C void DPrimaryMediaBase::NotifyMediaPresent() /** Notifies clients of a media change by calling NotifyClients ( ) function to indicate that media is present. */ { OstTraceFunctionEntry1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_ENTRY, this ); - NotifyClients(ETrue); + __KTRACE_OPT(KLOCDRV,Kern::Printf("DPrimaryMediaBase(%d)::NotifyMediaPresent state %d",iMediaId,iState)); + + // This should only be called in the context of the media thread + __ASSERT_ALWAYS(NKern::CurrentThread() == iDfcQ->iThread, LOCM_FAULT()); + + MediaChange(); + + NotifyClients(EMediaPresent); OstTraceFunctionExit1( DPRIMARYMEDIABASE_NOTIFYMEDIAPRESENT_EXIT, this ); } @@ -3575,10 +3855,10 @@ TInt id=iMediaId; // start with primary media TInt partitionsOnThisMedia=PartitionCount(); TInt partition=0; - TInt j; - for (j=0; jiPrimaryMedia==this) { if (totalPartitions==0) @@ -3939,7 +4219,7 @@ TInt retVal = KErrGeneral; for (TInt i=0; retVal != KErrNone && i < KPageInRetries; i++) { - m.Flags() = TLocDrvRequest::EPaging; + m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging; TLocDrv* pL=NULL; if(aDrvNumber == EDriveRomPaging) // ROM paging { @@ -3978,7 +4258,7 @@ m.Id() = DMediaPagingDevice::ECodePageInRequest; m.Flags() |= TLocDrvRequest::ECodePaging; pL=TheDrives[aDrvNumber]; - __ASSERT_DEBUG(pL&&(pL->iPrimaryMedia==iPrimaryMedia),LOCM_FAULT()); // valid drive number? + __ASSERT_DEBUG(pL && TDriveIterator::GetDrive(aDrvNumber, iPrimaryMedia) ,LOCM_FAULT()); // valid drive number? m.Drive()=pL; #ifdef __DEMAND_PAGING_BENCHMARKS__ __e32_atomic_add_ord32(&iMediaPagingInfo.iCodePageInCount, (TUint) 1); @@ -4101,7 +4381,7 @@ TInt retVal = KErrGeneral; for (TInt i=0; retVal != KErrNone && i < KPageOutRetries; i++) { - m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0); + m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging | (aBackground ? TLocDrvRequest::EBackgroundPaging : 0); m.Id() = DLocalDrive::EWrite; m.Drive() = TheDrives[iDataPagingDriveNumber]; @@ -4197,7 +4477,7 @@ TLocDrvRequest& m=*(TLocDrvRequest*)(aReq); - m.Flags() = TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging; + m.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EPaging | TLocDrvRequest::EDataPaging; m.Id() = DLocalDrive::EDeleteNotify; m.Drive() = TheDrives[iDataPagingDriveNumber]; @@ -4230,7 +4510,6 @@ } - EXPORT_C TInt TLocDrvRequest::WriteToPageHandler(const TAny* aSrc, TInt aSize, TInt anOffset) { OstTraceFunctionEntry1( TLOCDRVREQUEST_WRITETOPAGEHANDLER_ENTRY, this ); @@ -4418,6 +4697,28 @@ OstTraceFunctionExit1( DMEDIADRIVER_SETTOTALSIZEINBYTES_EXIT, this ); } +/** +For non NAND devices, i.e. devices which don't set TLocalDriveCapsV4::iNumOfBlocks, +set iSectorSizeInBytes, iNumberOfSectors & iNumPagesPerBlock appropriately to allow +TLocalDriveCapsV4::MediaSizeInBytes() to correctly return the media size + +Media drivers should call this when they receive a DLocalDrive::ECaps request +*/ +EXPORT_C void DMediaDriver::SetTotalSizeInBytes(TLocalDriveCapsV4& aCaps) + { + if (aCaps.iNumOfBlocks == 0) + { + aCaps.iSectorSizeInBytes = 512; + aCaps.iNumPagesPerBlock = 1; // ...to ensure compatibility with NAND semantics + Int64 numberOfSectors = iTotalSizeInBytes >> 9; + while (I64HIGH(numberOfSectors) > 0) + { + aCaps.iNumPagesPerBlock<<= 1; + numberOfSectors>>= 1; + } + aCaps.iNumberOfSectors = I64LOW(numberOfSectors); + } + } @@ -4649,37 +4950,25 @@ // Create TLocDrv / DMedia objects to handle a media device __KTRACE_OPT(KBOOT,Kern::Printf("RegisterMediaDevice %lS dev=%1d #drives=%d 1st=%d PM=%08x #media=%d",&aName,aDevice,aDriveCount,*aDriveList,aPrimaryMedia,aNumMedia)); OstTraceExt5( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE1, "aDevice=%d; aDriveCount=%d; aDriveList=%d; aPrimaryMedia=0x%08x; aNumMedia=%d", (TInt) aDevice, (TInt) aDriveCount, (TInt) *aDriveList, (TUint) aPrimaryMedia, (TInt) aNumMedia ); - - const TInt* p=aDriveList; - TInt i; - TInt r=0; + if (UsedMedia+aNumMedia>KMaxLocalDrives) { OstTrace0(TRACE_FLOW, LOCDRV_REGISTERMEDIADEVICE_EXIT1, "< KErrInUse"); return KErrInUse; - } - for (i=0; iiBody->iMediaExtension = ETrue; + + // Register the drives + const TInt* p=aDriveList; for (i=0; iiPrimaryMedia=aPrimaryMedia; - __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pL)); - OstTraceExt2( TRACE_INTERNALS, LOCDRV_REGISTERMEDIADEVICE5, "Drive=%d; TLocDrv 0x%08x;", (TInt) drv, (TUint) pL ); + } + + + TLocDrv* pOldDrive = TheDrives[drv]; + aPrimaryMedia->iBody->iRegisteredDriveMask|= (0x1 << drv); + pNewDrive->iNextDrive = pOldDrive; + + TheDrives[drv] = pNewDrive; + DriveNames[drv] = pN; + pNewDrive->iPrimaryMedia = aPrimaryMedia; + + + if (pOldDrive) + { + TInt r = pOldDrive->iPrimaryMedia->Connect(pNewDrive); + if (r != KErrNone) + return r; + +#ifdef __DEMAND_PAGING__ + // If we've hooked a drive letter which is being used for ROM paging by a media driver + // which does not report the ROM partition, then we need to change iFirstLocalDriveNumber + // so that ROM page-in requests go directly to that driver + DMediaPagingDevice* oldPagingDevice = pOldDrive->iPrimaryMedia->iBody->iPagingDevice; + if (oldPagingDevice && + (oldPagingDevice->iType & DPagingDevice::ERom) && + oldPagingDevice->iRomPagingDriveNumber == KErrNotFound && + oldPagingDevice->iFirstLocalDriveNumber == drv) + { + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: hooking ROM paging device with no defined ROM partition")); + TInt n; + for (n=0; niPrimaryMedia == pOldDrive->iPrimaryMedia) + { + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("TRACE: Changing iFirstLocalDriveNumber from %d to %d", oldPagingDevice->iFirstLocalDriveNumber, n)); + oldPagingDevice->iFirstLocalDriveNumber = n; + break; + } + } + __ASSERT_ALWAYS(n < KMaxLocalDrives, LOCM_FAULT()); + } +#endif + + } + + __KTRACE_OPT(KBOOT,Kern::Printf("Drive %d: TLocDrv @ %08x",drv,pNewDrive)); } + OstTraceFunctionExit0( LOCDRV_REGISTERMEDIADEVICE_EXIT7 ); return KErrNone; } @@ -4807,11 +5155,12 @@ EXPORT_C TInt LocDrv::RegisterPagingDevice(DPrimaryMediaBase* aPrimaryMedia, const TInt* aPagingDriveList, TInt aDriveCount, TUint aPagingType, TInt aReadShift, TUint aNumPages) { OstTraceFunctionEntry0( LOCDRV_REGISTERPAGINGDEVICE_ENTRY ); +// SETDEBUGFLAG(KLOCDPAGING); __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf(">RegisterPagingDevice: paging type=%d PM=0x%x read shift=%d",aPagingType,aPrimaryMedia,aReadShift)); OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE1, "aPagingType=%d; aPrimaryMedia=0x%x; aReadShift=%d", (TInt) aPagingType, (TUint) aPrimaryMedia, (TInt) aReadShift); - TInt i; + TInt i = 0; if(!aPagingType || (aPagingType&~(DPagingDevice::ERom | DPagingDevice::ECode | DPagingDevice::EData))) { @@ -4821,20 +5170,23 @@ } - - for(i=0; iiBody->iMediaExtension) { - if (ThePagingDevices[i] == NULL) - continue; - if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom)) + for(i=0; iiType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData)) - { - aPagingType&=~DPagingDevice::EData; // already have a Data paging device - __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i)); + if (ThePagingDevices[i] == NULL) + continue; + if ((ThePagingDevices[i]->iType&DPagingDevice::ERom) && (aPagingType & DPagingDevice::ERom)) + { + aPagingType&=~DPagingDevice::ERom; // already have a ROM paging device + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has ROM pager on locdrv no %d",i)); + } + if ((ThePagingDevices[i]->iType&DPagingDevice::EData) && (aPagingType & DPagingDevice::EData)) + { + aPagingType&=~DPagingDevice::EData; // already have a Data paging device + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("Already has Data pager on locdrv no %d",i)); + } } } @@ -4915,12 +5267,16 @@ // Send an ECaps message to wake up the media driver & ensure all partitions are // reported, then search for paged-data or paged-ROM partitions + // NB: older media drivers supporting ROM and/or code paging only may not have started their DFC queues, + // so for these media drivers, use the first local drive supported for ROM-pagin-in requests and + // assume the media driver itself will adjust the request position internally to match the ROM partition + // @see DMediaPagingDevice::Read() if ((aPagingType & DPagingDevice::EData) || (aPagingType & DPagingDevice::ERom && aPrimaryMedia->iDfcQ && aPrimaryMedia->iMsgQ.iReady)) { // the message queue must have been started already (by the media driver calling iMsgQ.Receive()) - // otherwise we can't send the DLocalDrive::EQueryDevice request - if (aPrimaryMedia->iDfcQ && !aPrimaryMedia->iMsgQ.iReady) + // otherwise we can't send the DLocalDrive::ECaps request + if (!aPrimaryMedia->iDfcQ || !aPrimaryMedia->iMsgQ.iReady) { __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Message queue not started")); OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT8, "< RegisterPagingDevice: Message queue not started; KErrNotReady"); @@ -4955,7 +5311,7 @@ if (r != KErrNone) { - OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< Caps::retval=%d - return KErrNotSupported",r); + OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r); // Media driver failure; media maybe recoverable after boot. // Can't register any page drives so return not supported. return KErrNotSupported; @@ -4967,20 +5323,25 @@ drive = TheDrives[i]; if(drive && drive->iPrimaryMedia == aPrimaryMedia) { - __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x size %x", i, drive->iPartitionType, I64LOW(drive->iPartitionLen))); + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("RegisterPagingDevice: local drive %d, partition type %x base %lx size %lx name %lS", i, drive->iPartitionType, drive->iPartitionBaseAddr, drive->iPartitionLen, DriveNames[i] ? DriveNames[i] : &KNullDesC8)); // ROM partition ? - if ((romPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypeROM)) + if ((romPagingDriveNumber == KErrNotFound) && + (drive->iPartitionType == KPartitionTypeROM) && + (aPagingType & DPagingDevice::ERom)) { __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found ROM partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE5, "Found ROM partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen)); romPagingDriveNumber = i; } // swap partition ? - else if ((dataPagingDriveNumber == KErrNotFound) && (drive->iPartitionType == KPartitionTypePagedData)) + else if ((dataPagingDriveNumber == KErrNotFound) && + (drive->iPartitionType == KPartitionTypePagedData) && + (aPagingType & DPagingDevice::EData)) { __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("Found swap partition on local drive %d, size %x", i, I64LOW(drive->iPartitionLen))); OstTraceDefExt2( OST_TRACE_CATEGORY_RND, TRACE_DEMANDPAGING, LOCDRV_REGISTERPAGINGDEVICE6, "Found SWAP partition on local drive=%d; size=0x%x", (TInt) i, (TUint) I64LOW(drive->iPartitionLen) ); dataPagingDriveNumber = i; + TheDataPagingDrive = drive; swapSize = drive->iPartitionLen >> aReadShift; } } @@ -5006,6 +5367,9 @@ } pagingDevice->iType = aPagingType; + if (aPrimaryMedia->iBody->iMediaExtension) + pagingDevice->iType|= DPagingDevice::EMediaExtension; + pagingDevice->iReadUnitShift = aReadShift; pagingDevice->iFirstLocalDriveNumber = firstLocalDriveNumber; @@ -5016,12 +5380,13 @@ #ifdef __DEBUG_DEMAND_PAGING__ Kern::Printf("PagingDevice :"); - Kern::Printf("iType 0x%x\n", pagingDevice->iType); - Kern::Printf("iReadUnitShift 0x%x\n", pagingDevice->iReadUnitShift); - Kern::Printf("iFirstLocalDriveNumber 0x%x\n", pagingDevice->iFirstLocalDriveNumber); - Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber); - Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber); - Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize); + Kern::Printf("Name %lS", firstLocalDriveNumber >= 0 && DriveNames[firstLocalDriveNumber] ? DriveNames[firstLocalDriveNumber] : &KNullDesC8); + Kern::Printf("iType 0x%x", pagingDevice->iType); + Kern::Printf("iReadUnitShift 0x%x", pagingDevice->iReadUnitShift); + Kern::Printf("iFirstLocalDriveNumber 0x%x", pagingDevice->iFirstLocalDriveNumber); + Kern::Printf("iRomPagingDriveNumber 0x%x", pagingDevice->iRomPagingDriveNumber); + Kern::Printf("iDataPagingDriveNumber 0x%x", pagingDevice->iDataPagingDriveNumber); + Kern::Printf("iSwapSize 0x%x", pagingDevice->iSwapSize); #endif @@ -5042,24 +5407,38 @@ if(aPagingType & DPagingDevice::ECode) { for (i=0; iiDrivesSupported|=(0x1<iDrivesSupported |= (0x1<iName = DeviceName[aPagingType]; + // If ThePinObjectAllocator has already been created with a smaller number of pages, + // delete it & then re-create it + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: ThePinObjectAllocator %x", ThePinObjectAllocator)); + if (ThePinObjectAllocator && ThePinObjectAllocator->iFragmentGranularity < Kern::RoundToPageSize(1) * aNumPages) + { + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: Recreating ThePinObjectAllocator...")); + delete ThePinObjectAllocator; + ThePinObjectAllocator = NULL; + } + + + TInt r; if (ThePinObjectAllocator == NULL) - ThePinObjectAllocator = new DPinObjectAllocator(); - if(!ThePinObjectAllocator) { - __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator")); - OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory"); - return KErrNoMemory; - } - TInt r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages); - if (r != KErrNone) - { - __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator")); - OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r); - return r; + ThePinObjectAllocator = new DPinObjectAllocator(); + if(!ThePinObjectAllocator) + { + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not create ThePinObjectAllocator")); + OstTrace0(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT11, "RegisterPagingDevice: could not create ThePinObjectAllocator; KErrNoMemory"); + return KErrNoMemory; + } + r = ThePinObjectAllocator->Construct(KDynamicPagingLockCount, aNumPages); + if (r != KErrNone) + { + __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("RegisterPagingDevice: could not construct ThePinObjectAllocator")); + OstTrace1(TRACE_FLOW, LOVDRV_REGISTERPAGINGDEVICE_EXIT12, "< RegisterPagingDevice: could not construct ThePinObjectAllocator; retval=%d",r); + return r; + } } @@ -5089,7 +5468,14 @@ for (i=0; iiPagingDrv=1; + pD->iPagingDrv = 1; + // mark all attached drives as pageable too - this is really + // only to avoid hitting an ASSERT in DMediaDriver::Complete() + while (pD->iNextDrive) + { + pD->iNextDrive->iPagingDrv = 1; + pD = pD->iNextDrive; + } } } @@ -5133,6 +5519,7 @@ __KTRACE_OPT2(KBOOT,KLOCDPAGING,Kern::Printf("< RegisterPagingDevice")); OstTraceFunctionExit0( LOCDRV_REGISTERPAGINGDEVICE_EXIT14 ); +// CLRDEBUGFLAG(KLOCDPAGING); return KErrNone; } @@ -5208,6 +5595,7 @@ TLocDrv* pL=TheDrives[i]; if (pL) { + pL = TDriveIterator::GetPhysicalDrive(TheDrives[i]); ++drives; TInt sockNum; DPrimaryMediaBase* pM=pL->iPrimaryMedia; @@ -5347,11 +5735,7 @@ #if defined(__DEMAND_PAGING__) && defined(__CONCURRENT_PAGING_INSTRUMENTATION__) case EMediaHalGetROMConcurrencyInfo: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5363,11 +5747,7 @@ } case EMediaHalGetCodeConcurrencyInfo: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5379,11 +5759,7 @@ } case EMediaHalGetDataConcurrencyInfo: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device = drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5395,17 +5771,20 @@ } case EMediaHalResetConcurrencyInfo: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; - if(!device) - break; TUint index=(TInt)a2; if(index>EMediaPagingStatsCode) break; - ResetConcurrencyStats(device, (TMediaPagingStats)index); + + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom); + if (device) + ResetConcurrencyStats(device, (TMediaPagingStats)index); + device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode); + if (device) + ResetConcurrencyStats(device, (TMediaPagingStats)index); + device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData); + if (device) + ResetConcurrencyStats(device, (TMediaPagingStats)index); + r=KErrNone; break; } @@ -5413,11 +5792,7 @@ #if defined(__DEMAND_PAGING__) && defined(__DEMAND_PAGING_BENCHMARKS__) case EMediaHalGetROMPagingBenchmark: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5429,11 +5804,7 @@ } case EMediaHalGetCodePagingBenchmark: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5445,11 +5816,7 @@ } case EMediaHalGetDataInPagingBenchmark: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5461,11 +5828,7 @@ } case EMediaHalGetDataOutPagingBenchmark: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5477,27 +5840,26 @@ } case EMediaHalResetPagingBenchmark: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; - if(!device) - break; TUint index=(TInt)a2; if(index>EMediaPagingStatsCode) break; - ResetBenchmarkStats(device, (TMediaPagingStats)index); + + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ERom); + if (device) + ResetBenchmarkStats(device, (TMediaPagingStats)index); + device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::ECode); + if (device) + ResetBenchmarkStats(device, (TMediaPagingStats)index); + device = TDriveIterator::PagingDevice((TInt)a1, DPagingDevice::EData); + if (device) + ResetBenchmarkStats(device, (TMediaPagingStats)index); + r=KErrNone; break; } case EMediaHalGetPagingInfo: { - TInt drvNo=(TInt)a1; - TLocDrv* drv=TheDrives[drvNo]; - if(!drv) - break; - DMediaPagingDevice* device=drv->iPrimaryMedia->iBody->iPagingDevice; + DMediaPagingDevice* device = TDriveIterator::PagingDevice((TInt)a1, (DPagingDevice::TType) 0xFF); if(!device) break; NKern::FMWait(&device->iInstrumentationLock); @@ -5737,6 +6099,309 @@ /****************************************************************************** + DMediaDriverExtension base class + ******************************************************************************/ + +EXPORT_C DMediaDriverExtension::DMediaDriverExtension(TInt aMediaId) : + DMediaDriver(aMediaId) + { + } + +/** +*/ +EXPORT_C DMediaDriverExtension::~DMediaDriverExtension() + { + } + +/** +Closes the media driver. + +This default implementation simply deletes this DMediaDriverExtension object. + +Media drivers can provide their own implementation, which gives them +the opportunity to clean up resources before closure; for example, +cancelling a DFC. +Any replacement function must call this base class function as +the last instruction. +*/ +EXPORT_C void DMediaDriverExtension::Close() + { + DMediaDriver::Close(); + } + +/** +DoDrivePartitionInfo() + +Fills out the passed TPartitionInfo object with information from the attached drives +*/ +EXPORT_C TInt DMediaDriverExtension::DoDrivePartitionInfo(TPartitionInfo& aInfo) + { + memclr(&aInfo, sizeof(aInfo)); + aInfo.iPartitionCount = 0; + aInfo.iMediaSizeInBytes = 0; + + TDriveIterator driveIter; + for (TLocDrv* drv = driveIter.NextDrive(); drv != NULL; drv = driveIter.NextDrive()) + { + if (drv && drv->iPrimaryMedia == iPrimaryMedia) + { + TLocDrv* attachedDrive = drv->iNextDrive; + __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); + TLocDrvRequest m; + memclr(&m, sizeof(m)); + + TBuf8 capsBuf; + capsBuf.SetMax(); + capsBuf.FillZ(); + m.Drive() = attachedDrive; + m.Id() = DLocalDrive::ECaps; + m.RemoteDes() = (TAny*)capsBuf.Ptr(); + m.Length() = KMaxLocalDriveCapsLength; + TInt r = attachedDrive->iPrimaryMedia->Request(m); + + __KTRACE_OPT2(KBOOT,KLOCDPAGING, Kern::Printf("DMediaDriverExtension::PartitionInfo(ECaps: i %d: r %d ", driveIter.Index(), r)); + + // NB The ECaps call might legitimately fail if one of the attached drives is removable + // If this happens, just ignore & proceed to the next attached drive + if (r == KErrNone) + { + aInfo.iEntry[aInfo.iPartitionCount] = *attachedDrive; + // Set the media size to be that of the largest attached media + // This is only needed to ensure that the test in TLocDrvRequest::CheckAndAdjustForPartition() + // with the ELocDrvWholeMedia flag set succeeds: A further check on whether a request's + // position & length are outside the media will be made when its is delievered to the attached media.... + aInfo.iMediaSizeInBytes = Max( + aInfo.iMediaSizeInBytes, + ((TLocalDriveCapsV4*) capsBuf.Ptr())->MediaSizeInBytes()); + } + + + aInfo.iPartitionCount++; + } + } + + return KErrNone; + } + +/** +ForwardRequest() - + +forwards the request onto the next attached drive in the chain +*/ +EXPORT_C TInt DMediaDriverExtension::ForwardRequest(TLocDrvRequest& aRequest) + { + TLocDrv* drive = aRequest.Drive(); + TLocDrv* attachedDrive = drive->iNextDrive; + __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); + aRequest.Drive() = attachedDrive; + + + TInt r = attachedDrive->iPrimaryMedia->HandleMediaNotPresent(aRequest); + if (r != KErrNone) + { + return r; + } + + aRequest.Forward(&attachedDrive->iPrimaryMedia->iMsgQ, EFalse); + return KErrNone; + } + + +TInt DMediaDriverExtension::SendRequest(TInt aReqId, TBool aPagingRequest, TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) + { + __ASSERT_DEBUG(aLen > 0, LOCM_FAULT()); + + // Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice() + if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber))) + return KErrArgument; + + TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); + __ASSERT_DEBUG(drive, LOCM_FAULT()); + TLocDrv* attachedDrive = drive->iNextDrive; + __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); + + TLocDrvRequest request; + memclr(&request, sizeof(request)); + + request.Drive() = attachedDrive; + request.Id() = aReqId; + request.Length() = aLen; + request.RemoteDes() = (TAny*) aData; + request.Pos() = aPos; + request.Flags() = TLocDrvRequest::EKernelBuffer | TLocDrvRequest::EAdjusted; + +#ifdef __DEMAND_PAGING__ + if (aPagingRequest) + { + request.Flags()|= TLocDrvRequest::EPaging; + // If the buffer is page aligned, use SendToMainQueueDfcAndBlock() as this + // is more efficient if the attached drive use DMA. + const TInt KPageSizeMask = 4096-1; + if (aData & KPageSizeMask) + { + return attachedDrive->iPrimaryMedia->SendReceive(request, aData); + } + else + { + attachedDrive->iPrimaryMedia->iBody->iPagingDevice->SendToMainQueueDfcAndBlock(&request); + return 0; + } + } +#else + aPagingRequest; +#endif + + return attachedDrive->iPrimaryMedia->SendReceive(request, aData); + } + + +/** +Read() - + +reads data from the next attached drive in the chain + +N.B. The position is assumed to be already adjusted i.e. relative to the start of the +media, not the partition +*/ +EXPORT_C TInt DMediaDriverExtension::Read(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) + { + return SendRequest(DLocalDrive::ERead, EFalse, aDriveNumber, aPos, aData, aLen); + } + +/** +Write() - + +writes data to the next attached drive in the chain + +N.B. The position is assumed to be already adjusted i.e. relative to the start of the +media, not the partition +*/ +EXPORT_C TInt DMediaDriverExtension::Write(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) + { + return SendRequest(DLocalDrive::EWrite, EFalse, aDriveNumber, aPos, aData, aLen); + } + + +#ifdef __DEMAND_PAGING__ +/** +ReadPaged() - + +Sends a paging read request to the specified attached drive + +N.B. The position is assumed to be already adjusted i.e. relative to the start of the +media, not the partition +*/ +EXPORT_C TInt DMediaDriverExtension::ReadPaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) + { + return SendRequest(DLocalDrive::ERead, ETrue, aDriveNumber, aPos, aData, aLen); + } + +/** +WritePaged() - + +Send a paging write request to the specified attached drive + +N.B. The position is assumed to be already adjusted i.e. relative to the start of the +media, not the partition +*/ +EXPORT_C TInt DMediaDriverExtension::WritePaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen) + { + return SendRequest(DLocalDrive::EWrite, ETrue, aDriveNumber, aPos, aData, aLen); + } +#endif // __DEMAND_PAGING__ + + + +/** +Caps() - + +gets the caps from the next attached drive in the chain + +N.B. The position is assumed to be already adjusted i.e. relative to the start of the +media, not the partition +*/ +EXPORT_C TInt DMediaDriverExtension::Caps(TInt aDriveNumber, TDes8& aCaps) + { + // Ensure this is a legitimate attached drive registered using LocDrv::RegisterMediaDevice() + if (!(iPrimaryMedia->iBody->iRegisteredDriveMask & (0x1 << aDriveNumber))) + return KErrArgument; + + TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); + __ASSERT_DEBUG(drive, LOCM_FAULT()); + TLocDrv* attachedDrive = drive->iNextDrive; + __ASSERT_DEBUG(attachedDrive, LOCM_FAULT()); + + TLocDrvRequest request; + memclr(&request, sizeof(request)); + + request.Drive() = attachedDrive; + request.Id() = DLocalDrive::ECaps; + request.Length() = aCaps.Length(); + request.RemoteDes() = (TAny*) aCaps.Ptr(); + + return request.SendReceive(&attachedDrive->iPrimaryMedia->iMsgQ); + } + + + +EXPORT_C void DMediaDriverExtension::NotifyPowerDown() + { + } + +EXPORT_C void DMediaDriverExtension::NotifyEmergencyPowerDown() + { + } + + +/** +Returns ETrue if this media - or any media which this TLocDrv is attached to - is busy +*/ +EXPORT_C TBool DMediaDriverExtension::MediaBusy(TInt aDriveNumber) + { + for (TLocDrv* drive = TDriveIterator::GetDrive(aDriveNumber, iPrimaryMedia); + drive; + drive = drive->iNextDrive) + { + DPrimaryMediaBase* primaryMedia = drive->iPrimaryMedia; + __ASSERT_DEBUG(primaryMedia, LOCM_FAULT()); + + if ((primaryMedia->iMsgQ.iMessage && primaryMedia->iMsgQ.iMessage->iState != TMessageBase::EFree) || + !primaryMedia->iMsgQ.iQ.IsEmpty() || + primaryMedia->iBody->iMediaChangeDfc.Queued() || + primaryMedia->iBody->iMediaPresentDfc.Queued()) + return ETrue; + +#ifdef __DEMAND_PAGING__ + DMediaPagingDevice* pagingDevice = iPrimaryMedia->iBody->iPagingDevice; + if (pagingDevice) + { + if ((pagingDevice->iMainQ.iMessage && pagingDevice->iMainQ.iMessage->iState != TMessageBase::EFree) || + !pagingDevice->iMainQ.iQ.IsEmpty()) + return ETrue; + } +#endif + } + + return EFalse; + } + + +TCallBackLink::TCallBackLink() + { + memclr(this, sizeof(this)); + } + +TCallBackLink::TCallBackLink(TInt (*aFunction)(TAny* aPtr, TInt aParam),TAny* aPtr, TObjectType aObjectType) : + iFunction(aFunction), iPtr(aPtr), iObjectType(aObjectType) + { + } + +TInt TCallBackLink::CallBack(TInt aParam) const + { + return (*iFunction)(iPtr, aParam); + } + +/****************************************************************************** Entry point ******************************************************************************/ DECLARE_STANDARD_EXTENSION() @@ -5745,6 +6410,7 @@ // install the HAL function TInt r=Kern::AddHalEntry(EHalGroupMedia,MediaHalFunction,NULL); + #ifdef __DEMAND_PAGING__ if (r==KErrNone) { @@ -5757,6 +6423,7 @@ __KTRACE_OPT(KBOOT,Kern::Printf("Installing LocDrv device in kernel returned %d",r)); } #endif // __DEMAND_PAGING__ + return r; } diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/medata/pccd_ata.cpp --- a/kernel/eka/drivers/medata/pccd_ata.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/medata/pccd_ata.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -1785,6 +1785,7 @@ aInfo.iFileSystemId=KDriveFileSysFAT; aInfo.iHiddenSectors=iHiddenSectors; aInfo.iBlockSize=KAtaSectorSize; + SetTotalSizeInBytes(aInfo); return KErrCompletion; // synchronous completion } diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/medint/iram.cpp --- a/kernel/eka/drivers/medint/iram.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/medint/iram.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -200,6 +200,7 @@ caps.iEraseBlockSize=TInternalRamDrive::MaxSize(); // overload for RAM drive to avoid // F32 depending on memory model caps.iBlockSize=1; + SetTotalSizeInBytes(caps); return KErrNone; } diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/medlfs/flash_media.cpp --- a/kernel/eka/drivers/medlfs/flash_media.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/medlfs/flash_media.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -163,10 +163,11 @@ __KTRACE_OPT(KLOCDRV,Kern::Printf(">DMediaDriverFlash::Request %d",id)); if (id==DLocalDrive::ECaps) { - TLocalDriveCapsV2& c=*(TLocalDriveCapsV2*)m.RemoteDes(); + TLocalDriveCapsV4& c=*(TLocalDriveCapsV4*)m.RemoteDes(); r=Caps(c); c.iSize=m.Drive()->iPartitionLen; c.iPartitionType=m.Drive()->iPartitionType; + SetTotalSizeInBytes(c); return r; } switch (id) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/drivers/medmmc/medmmc.cpp --- a/kernel/eka/drivers/medmmc/medmmc.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/drivers/medmmc/medmmc.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -797,17 +797,8 @@ } else { -#if defined(__DEMAND_PAGING__) && !defined(__WINS__) - if (DMediaPagingDevice::PageInRequest(*iCurrentReq)) - { - r = iCurrentReq->WriteToPageHandler(NULL, 0, 0); - } - else -#endif // __DEMAND_PAGING__ - { - TPtrC8 zeroDes(NULL, 0); - r = iCurrentReq->WriteRemote(&zeroDes,0); - } + TPtrC8 zeroDes(NULL, 0); + r = iCurrentReq->WriteRemote(&zeroDes,0); } // error occurred or read all from cache so complete immediately @@ -2957,12 +2948,7 @@ TUint usrOfst = I64LOW(iReqCur - iReqStart); OstTrace0( TRACE_INTERNALS, DMMCMEDIADRIVERFLASH_WRITEDATATOUSER_LATENCY1, "Begin writing user data" ); -#if defined(__DEMAND_PAGING__) && !defined(__WINS__) - if (DMediaPagingDevice::PageInRequest(*iCurrentReq)) - r=iCurrentReq->WriteToPageHandler((TUint8 *)(&extrView[0]), len, usrOfst); - else -#endif // __DEMAND_PAGING__ - r = iCurrentReq->WriteRemote(&extrView,usrOfst); + r = iCurrentReq->WriteRemote(&extrView,usrOfst); OstTrace0( TRACE_INTERNALS, DMMCMEDIADRIVERFLASH_WRITEDATATOUSER_LATENCY2, "End writing user data" ); @@ -2973,19 +2959,10 @@ TInt DMmcMediaDriverFlash::ReadDataFromUser(TDes8& aDes, TInt aOffset) { OstTraceExt2(TRACE_FLOW, DMMCMEDIADRIVERFLASH_READDATAFROMUSER_ENTRY ,"DMmcMediaDriverFlash::ReadDataFromUser;aOffset=%d;this=%x", aOffset, (TUint) this); - TInt r = KErrNotSupported; -#ifndef __WINS__ - if (DMediaPagingDevice::PageOutRequest(*iCurrentReq)) - { - r = iCurrentReq->ReadFromPageHandler((TAny*) aDes.Ptr(), aDes.MaxLength(), aOffset); - OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_READDATAFROMUSER_EXIT1, this, r ); - return r; - } - else -#endif // #ifndef __WINS__ - r = iCurrentReq->ReadRemote(&aDes, aOffset); - - OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_READDATAFROMUSER_EXIT2, this, r ); + + TInt r = iCurrentReq->ReadRemote(&aDes, aOffset); + + OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_READDATAFROMUSER_EXIT1, this, r ); return r; } @@ -3698,6 +3675,7 @@ c.iSize = drive.iPartitionLen; c.iPartitionType = drive.iPartitionType; c.iHiddenSectors = (TUint) (drive.iPartitionBaseAddr >> KDiskSectorShift); + SetTotalSizeInBytes(c); OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_REQUEST_EXIT1, this, r ); return r; } diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/eabi/elocdu.def --- a/kernel/eka/eabi/elocdu.def Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/eabi/elocdu.def Fri Apr 23 22:20:31 2010 +0100 @@ -64,4 +64,23 @@ _ZTI10DDmaHelper @ 63 NONAME ; ## _ZTV10DDmaHelper @ 64 NONAME ; ## _ZN14TLocDrvRequest19ReadFromPageHandlerEPvii @ 65 NONAME + _ZN21DMediaDriverExtension14ForwardRequestER14TLocDrvRequest @ 66 NONAME + _ZN21DMediaDriverExtension15NotifyPowerDownEv @ 67 NONAME + _ZN21DMediaDriverExtension20DoDrivePartitionInfoER14TPartitionInfo @ 68 NONAME + _ZN21DMediaDriverExtension24NotifyEmergencyPowerDownEv @ 69 NONAME + _ZN21DMediaDriverExtension4CapsEiR5TDes8 @ 70 NONAME + _ZN21DMediaDriverExtension4ReadEixmj @ 71 NONAME + _ZN21DMediaDriverExtension5CloseEv @ 72 NONAME + _ZN21DMediaDriverExtension5WriteEixmj @ 73 NONAME + _ZN21DMediaDriverExtension9MediaBusyEi @ 74 NONAME + _ZN21DMediaDriverExtensionC2Ei @ 75 NONAME + _ZN21DMediaDriverExtensionD0Ev @ 76 NONAME + _ZN21DMediaDriverExtensionD1Ev @ 77 NONAME + _ZN21DMediaDriverExtensionD2Ev @ 78 NONAME + _ZTI21DMediaDriverExtension @ 79 NONAME + _ZTV21DMediaDriverExtension @ 80 NONAME + _ZN12DMediaDriver19SetTotalSizeInBytesER17TLocalDriveCapsV4 @ 81 NONAME + _ZN21DMediaDriverExtension10WritePagedEixmj @ 82 NONAME + _ZN21DMediaDriverExtension9ReadPagedEixmj @ 83 NONAME + _ZN11DLocalDrive4CapsEiR5TDes8 @ 84 NONAME diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/include/d32locd.h --- a/kernel/eka/include/d32locd.h Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/include/d32locd.h Fri Apr 23 22:20:31 2010 +0100 @@ -36,17 +36,22 @@ enum TMediaDevice { EFixedMedia0, EFixedMedia1, EFixedMedia2, EFixedMedia3, EFixedMedia4, EFixedMedia5, EFixedMedia6, EFixedMedia7, ERemovableMedia0, ERemovableMedia1, ERemovableMedia2, ERemovableMedia3, - EInvalidMedia + EInvalidMedia, + EMediaExtension0, EMediaExtension1, EMediaExtension2, EMediaExtension3, + EMediaExtension4, EMediaExtension5, EMediaExtension6, EMediaExtension7, }; #define __IS_REMOVABLE(aDevice) (aDevice>=ERemovableMedia0 && aDevice<=ERemovableMedia3) #define __IS_FIXED(aDevice) ((TUint)aDevice<=EFixedMedia7) +#define __IS_EXTENSION(aDevice) (aDevice>=EMediaExtension0 && aDevice<=EMediaExtension7) + #define MEDIA_DEVICE_IRAM EFixedMedia0 #define MEDIA_DEVICE_LFFS EFixedMedia1 #define MEDIA_DEVICE_NAND EFixedMedia2 #define MEDIA_DEVICE_MMC ERemovableMedia0 #define MEDIA_DEVICE_PCCARD ERemovableMedia1 #define MEDIA_DEVICE_CSA ERemovableMedia2 +#define MEDIA_DEVICE_NFE EMediaExtension0 typedef signed int TSocket; @@ -506,6 +511,16 @@ }; typedef TPckgBuf TPageDeviceInfoBuf; +class TLocalDriveFinaliseInfo +/** +@internalTechnology +*/ + { +public: + TInt iMode; // @see RFs::TFinaliseDrvMode + }; +typedef TPckgBuf TLocalDriveFinaliseInfoBuf; + class RLocalDrive : public RBusLogicalChannel /** Interface class to local media @@ -553,6 +568,7 @@ ELocDrvWholeMedia = 0x40000000 /**< Set to access whole media, rather than partition */ }; + // @see TBusLocalDrive::QueryDevice() enum TQueryDevice { // Symbian publishedPartner range @@ -567,7 +583,14 @@ EQueryLicenseeFirst = 0x8000, EQueryLicenseeLast = 0xBFFF, + // Finalize Drive - called as a result of a call to RFs::FinaliseDrives() + EQueryFinaliseDrive = EQuerySymbianPublishedPartnerFirst + 0, // @internalTechnology + EQueryPageDeviceInfo = EQuerySymbianTestFirst, /**< @see TPageDeviceInfo */ + + // NFE test driver + EQuerySymbianNfeTestFirst = EQuerySymbianTestFirst+0x10, + EQuerySymbianNfeTestEnd = EQuerySymbianTestFirst+0x1F, }; public: inline TVersion VersionRequired() const; diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/include/drivers/locmedia.h --- a/kernel/eka/include/drivers/locmedia.h Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/include/drivers/locmedia.h Fri Apr 23 22:20:31 2010 +0100 @@ -166,6 +166,46 @@ class TLocDrvRequest; class DPrimaryMediaBase; +/* +TCallBackLink + +@internalComponent + +Internal class which allows a list of callbacks to be linked together. +*/ + +NONSHARABLE_CLASS(TCallBackLink) + { +public: + enum TObjectType + { + EDLocalDriveObject, // object containing this TCallBackLink is a DLocalDrive + ETLocDrvObject, // object containing this TCallBackLink is a TLocDrv + }; + +public: + TCallBackLink(); + TCallBackLink(TInt (*aFunction)(TAny* aPtr, TInt aParam),TAny* aPtr, TObjectType aObjectType); + TInt CallBack(TInt aParam) const; +public: + /** + A pointer to the callback function. + */ + TInt (*iFunction)(TAny* aPtr, TInt aParam); + + + /** + A pointer that is passed to the callback function when + the function is called. + */ + TAny* iPtr; + + TObjectType iObjectType; + + SDblQueLink iLink; + }; + + /** @publishedPartner @released @@ -275,19 +315,22 @@ Query device */ EQueryDevice=32, - }; public: DLocalDrive(); ~DLocalDrive(); -public: + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); /**< @internalComponent */ virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2); /**< @internalComponent */ -public: - void NotifyChange(DPrimaryMediaBase& aPrimaryMedia, TBool aMediaChange); -public: + + void NotifyChange(); + inline void Deque(); /**< @internalComponent */ + static TInt MediaChangeCallback(TAny* aLocalDrive, TInt aNotifyType); /**< @internalComponent */ + + IMPORT_C static TInt Caps(TInt aDriveNumber, TDes8& aCaps); + private: #ifdef __DEMAND_PAGING__ TInt LockMountInfo(DPrimaryMediaBase& aPrimaryMedia, TLocDrvRequest& aReq); @@ -296,10 +339,10 @@ TInt ReadPasswordData(TLocDrvRequest& aReq, TLocalDrivePasswordData& aPswData, TMediaPassword& aOldPasswd, TMediaPassword& aNewPasswd); public: - TLocDrv* iDrive; /**< @internalComponent */ - SDblQueLink iLink; /**< @internalComponent */ + TLocDrv* iDrive; /**< @internalComponent */ + TCallBackLink iMediaChangeObserver; /**< @internalComponent */ TClientDataRequest* iNotifyChangeRequest; /**< @internalComponent */ - TLocalDriveCleanup iCleanup; /**< @internalComponent */ + TLocalDriveCleanup iCleanup; /**< @internalComponent */ }; /** @@ -341,7 +384,7 @@ ECodePaging=0x20, // a code paging request EDataPaging=0x40, // a data paging request ETClientBuffer=0x80, // RemoteDes() points to a TClientBuffer - EKernelBuffer=0x100, // RemoteDes() points to a kernel-side buffer + EKernelBuffer=0x100, // RemoteDes() points to a kernel-side buffer : set for all paging requests and media extension requests }; public: @@ -493,7 +536,7 @@ @internalComponent */ inline void DLocalDrive::Deque() - { iLink.Deque(); } + { iMediaChangeObserver.iLink.Deque(); } @@ -647,6 +690,7 @@ inline TInt Connect(DLocalDrive* aLocalDrive); inline void Disconnect(DLocalDrive* aLocalDrive); inline TInt Request(TLocDrvRequest& aRequest); + static TInt MediaChangeCallback(TAny* aLocDrv, TInt aNotifyType); public: TInt iDriveNumber; DMedia* iMedia; @@ -661,6 +705,14 @@ TUint8 iSpare3; #endif DDmaHelper* iDmaHelper; + + // Media extension stuff: + + /** ptr to the next TLocDrv object in the chain. Null if not a media extension */ + TLocDrv* iNextDrive; + + /** media change callback - called when the next media in the chain has a media change */ + TCallBackLink iMediaChangeObserver; }; /** @@ -827,7 +879,7 @@ public: IMPORT_C DPrimaryMediaBase(); -public: + // provided by implementation IMPORT_C virtual TInt Create(TMediaDevice aDevice, TInt aMediaId, TInt aLastMediaId); IMPORT_C virtual TInt Connect(DLocalDrive* aLocalDrive); @@ -841,7 +893,7 @@ IMPORT_C virtual void DeltaCurrentConsumption(TInt aCurrent); IMPORT_C virtual void DefaultDriveCaps(TLocalDriveCapsV2& aCaps); IMPORT_C virtual TBool IsRemovableDevice(TInt& aSocketNum); -public: + // used by implementation IMPORT_C void NotifyMediaChange(); IMPORT_C void NotifyPowerDown(); @@ -849,7 +901,7 @@ IMPORT_C void NotifyPsuFault(TInt anError); IMPORT_C void NotifyMediaPresent(); IMPORT_C void PowerUpComplete(TInt anError); -public: + IMPORT_C virtual void HandleMsg(TLocDrvRequest& aRequest); IMPORT_C virtual TInt DoRequest(TLocDrvRequest& aRequest); TInt OpenMediaDriver(); @@ -862,7 +914,10 @@ void CompleteRequest(TLocDrvRequest& aMsg, TInt aResult); IMPORT_C void RunDeferred(); void SetClosed(TInt anError); - void NotifyClients(TBool aMediaChange,TLocDrv* aLocDrv=NULL); + + enum TNotifyType {EMediaChange, EMediaPresent}; + void NotifyClients(TNotifyType aNotifyType, TLocDrv* aLocDrv=NULL); + TInt InCritical(); void EndInCritical(); void UpdatePartitionInfo(); @@ -882,6 +937,13 @@ void RequestCountDec(); #endif + // called by LocDrv::RegisterMediaDevice() for media extensions + TInt Connect(TLocDrv* aLocDrv); + + void MediaChange(); + TInt HandleMediaNotPresent(TLocDrvRequest& aReq); + + public: TInt iLastMediaId; /**< @internalComponent */ TMessageQue iMsgQ; @@ -1148,6 +1210,7 @@ virtual void NotifyEmergencyPowerDown()=0; public: IMPORT_C void SetTotalSizeInBytes(Int64 aTotalSizeInBytes, TLocDrv* aLocDrv=NULL); + IMPORT_C void SetTotalSizeInBytes(TLocalDriveCapsV4& aCaps); IMPORT_C Int64 TotalSizeInBytes(); IMPORT_C void SetCurrentConsumption(TInt aValue); IMPORT_C TInt InCritical(); @@ -1165,6 +1228,74 @@ }; +/** +@internalTechnology +@prototype + +An abstract base class for media driver 'extensions' within the local media subsystem +*/ +class DMediaDriverExtension : public DMediaDriver + { +public: + IMPORT_C DMediaDriverExtension(TInt aMediaId); + IMPORT_C virtual ~DMediaDriverExtension(); + IMPORT_C virtual void Close(); + + virtual TInt Request(TLocDrvRequest& aRequest) = 0; + + virtual TInt PartitionInfo(TPartitionInfo &anInfo) = 0; + + IMPORT_C virtual void NotifyPowerDown(); + + IMPORT_C virtual void NotifyEmergencyPowerDown(); + + /** + Retrieve partition info from all the attached drives + */ + IMPORT_C TInt DoDrivePartitionInfo(TPartitionInfo &anInfo); + /** + Forward a request to the next attached drive + */ + IMPORT_C TInt ForwardRequest(TLocDrvRequest& aRequest); + + /** + Read from the specified attached drive + */ + IMPORT_C TInt Read(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen); + + /** + Write to the specified attached drive + */ + IMPORT_C TInt Write(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen); + + /** + Get the Caps from the specified attached drive + */ + IMPORT_C TInt Caps(TInt aDriveNumber, TDes8& aCaps); + + /** + Return whether the media is busy i.e. if it has any pending requests or DFCs + */ + IMPORT_C TBool MediaBusy(TInt aDriveNumber); + +#ifdef __DEMAND_PAGING__ + /** + Send a paging read request to the specified attached drive + */ + IMPORT_C TInt ReadPaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen); + + /** + Send a paging write request to the specified attached drive + */ + IMPORT_C TInt WritePaged(TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen); +#endif + +private: + TInt SendRequest(TInt aReqId, TBool aPagingRequest, TInt aDriveNumber, TInt64 aPos, TLinAddr aData, TUint aLen); + + }; + + /** diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/include/e32ver.h --- a/kernel/eka/include/e32ver.h Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/include/e32ver.h Fri Apr 23 22:20:31 2010 +0100 @@ -28,7 +28,7 @@ const TInt KE32MajorVersionNumber=2; const TInt KE32MinorVersionNumber=0; -const TInt KE32BuildVersionNumber=3064; +const TInt KE32BuildVersionNumber=3066; const TInt KMachineConfigurationMajorVersionNumber=1; const TInt KMachineConfigurationMinorVersionNumber=0; diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/memmodel/epoc/flexible/mmu/mcodepaging.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mcodepaging.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mcodepaging.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -64,7 +64,7 @@ */ static DCodePagedMemoryManager TheManager; - friend DPagingDevice* CodePagingDevice(TInt aDiveNum); + friend DPagingDevice* CodePagingDevice(TInt aDriveNum); }; @@ -131,6 +131,8 @@ { TRACEB(("DCodePagedMemoryManager::InstallPagingDevice drive=%d",i)); TAny* null = 0; + if(aDevice->iType & DPagingDevice::EMediaExtension) + __e32_atomic_store_ord_ptr(&iDevice[i], null); if(!__e32_atomic_cas_ord_ptr(&iDevice[i], &null, aDevice)) // set iDevice[i]=aDevice if it was originally 0 { // paging device already registered... @@ -207,11 +209,11 @@ TInt DCodePagedMemoryManager::CleanPage(DMemoryObject* aMemory, SPageInfo* aPageInfo, TPhysAddr*& aPageArrayEntry) { - if(aPageInfo->IsDirty()==false) + if(!aPageInfo->IsDirty()) return KErrNone; // shouldn't be asked to clean a page which is writable... - __NK_ASSERT_DEBUG(aPageInfo->IsWritable()==false); + __NK_ASSERT_DEBUG(!aPageInfo->IsWritable()); // Note, memory may have been modified by the CodeModifier class. diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -656,6 +656,15 @@ } // Store the device, blocking any other devices from installing. + // unless the device is a media extension device + if(aDevice->iType & DPagingDevice::EMediaExtension) + { + delete iSwapManager; + iSwapManager = NULL; + TAny* null = 0; + __e32_atomic_store_ord_ptr(&iDevice, null); + } + if (!NKern::CompareAndSwap((TAny*&)iDevice, (TAny*)NULL, (TAny*)aDevice)) {// Data paging device already installed. __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("**** Attempt to install more than one data paging device !!!!!!!! ****")); diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/memmodel/epoc/flexible/mmu/mrom.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mrom.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mrom.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -502,6 +502,8 @@ } TAny* null = 0; + if(aDevice->iType & DPagingDevice::EMediaExtension) + __e32_atomic_store_ord_ptr(&iDevice, null); if(!__e32_atomic_cas_ord_ptr(&iDevice, &null, aDevice)) // set iDevice=aDevice if it was originally 0 { // ROM paging device already registered... @@ -969,6 +971,11 @@ MmuLock::Lock(); SPageInfo::FromPhysAddr(iNewPage)->SetShadow(aIndex,aMemory->PageInfoFlags()); MmuLock::Unlock(); + +#ifdef BTRACE_KERNEL_MEMORY + BTrace4(BTrace::EKernelMemory, BTrace::EKernelMemoryMiscAlloc, KPageSize); + ++Epoc::KernelMiscPages; +#endif } RamAllocLock::Unlock(); @@ -992,6 +999,11 @@ { RamAllocLock::Lock(); TheMmu.FreeRam(&iNewPage, 1, EPageFixed); + +#ifdef BTRACE_KERNEL_MEMORY + BTrace4(BTrace::EKernelMemory, BTrace::EKernelMemoryMiscFree, KPageSize); + --Epoc::KernelMiscPages; +#endif RamAllocLock::Unlock(); } if(IsAttached()) diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/memmodel/epoc/mmubase/mmubase.cpp --- a/kernel/eka/memmodel/epoc/mmubase/mmubase.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/memmodel/epoc/mmubase/mmubase.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -651,6 +651,17 @@ } +TInt MmuBase::FreeRamZone(TUint aZoneId, TPhysAddr& aZoneBase, TUint& aZoneBytes) + { + TUint zonePages; + TInt r = iRamPageAllocator->GetZoneAddress(aZoneId, aZoneBase, zonePages); + if (r != KErrNone) + return r; + aZoneBytes = zonePages << KPageShift; + return MmuBase::FreePhysicalRam(aZoneBase, aZoneBytes); + } + + TInt MmuBase::ClaimPhysicalRam(TPhysAddr aPhysAddr, TInt aSize) { __KTRACE_OPT(KMMU,Kern::Printf("Mmu::ClaimPhysicalRam(%08x,%x)",aPhysAddr,aSize)); @@ -1263,14 +1274,14 @@ #endif #ifdef BTRACE_RAM_ALLOCATOR - // Must check for -1 as that is the default value of aCategroy for + // Must check for -1 as that is the default value of aCategory for // BTrace::Prime() which is intended to prime all categories that are // currently enabled via a single invocation of BTrace::Prime(). if(aCategory==BTrace::ERamAllocator || (TInt)aCategory == -1) { NKern::ThreadEnterCS(); Mmu::Wait(); - Mmu::Get().iRamPageAllocator->SendInitialBtraceLogs(); + Mmu::Get().iRamPageAllocator->DoBTracePrime(); Mmu::Signal(); NKern::ThreadLeaveCS(); } @@ -2051,6 +2062,45 @@ /** +Free a RAM zone which was previously allocated by one of these methods: +Epoc::AllocPhysicalRam(), Epoc::ZoneAllocPhysicalRam() or +TRamDefragRequest::ClaimRamZone(). + +All of the pages in the RAM zone must be allocated and only via one of the methods +listed above, otherwise a system panic will occur. + +@param aZoneId The ID of the RAM zone to free. +@return KErrNone If the operation was successful. + KErrArgument If a RAM zone with ID aZoneId was not found. + +@pre Calling thread must be in a critical section. +@pre Interrupts must be enabled. +@pre Kernel must be unlocked. +@pre No fast mutex can be held. +@pre Call in a thread context. +@pre Can be used in a device driver. +*/ +EXPORT_C TInt Epoc::FreeRamZone(TUint aZoneId) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::FreeRamZone"); + MmuBase& m = *MmuBase::TheMmu; + MmuBase::Wait(); + TPhysAddr zoneBase; + TUint zoneBytes; + TInt r = m.FreeRamZone(aZoneId, zoneBase, zoneBytes); +#ifdef BTRACE_KERNEL_MEMORY + if (r == KErrNone) + { + BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysFree, zoneBytes, zoneBase); + Epoc::DriverAllocdPhysRam -= zoneBytes; + } +#endif + MmuBase::Signal(); + return r; + } + + +/** Translate a virtual address to the corresponding physical address. @param aLinAddr The virtual address to be translated. @@ -3244,7 +3294,7 @@ { NKern::LockSystem(); SPagingDevice* device = &iPagingDevices[aId]; - if(device->iInstalled) + if((device->iInstalled) && !(aDevice->iType & DPagingDevice::EMediaExtension)) { __KTRACE_OPT2(KPAGING,KBOOT,Kern::Printf("**** Attempt to install more than one ROM paging device !!!!!!!! ****")); //Panic(EDeviceAlreadyExists); diff -r 70ba09fd07a5 -r fc55edbf3919 kernel/eka/release.txt --- a/kernel/eka/release.txt Fri Apr 23 22:14:19 2010 +0100 +++ b/kernel/eka/release.txt Fri Apr 23 22:20:31 2010 +0100 @@ -1,3 +1,23 @@ +Version 2.00.3066 +================= +(Made by vfebvre 15/04/2010) + +1. migubarr + 1. REQ 415-7212 NFE drive encryption on Demand Paging-enabled device + PackageReleaseID=453228 FeatureReleaseID=447937 + + +Version 2.00.3065 +================= +(Made by vfebvre 15/04/2010) + +1. ahiron + 1. DEF145202: E32TEST T_IIC test failure investigation (KERN-EXEC 17) + +2. vfebvre + 1. MINOR_CHANGE Temporarily disable crash-prone test T_SOUND2 until it is fixed (DEF144934) + + Version 2.00.3064 ================= (Made by vfebvre 14/04/2010) diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/iic/t_iic.cpp --- a/kerneltest/e32test/iic/t_iic.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/e32test/iic/t_iic.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -1522,6 +1522,8 @@ gChanSlaveI2c.Close(); UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); +// Not safe to assume that heap clean-up has completed for the channels just closed, so insert a delay.(DEF145202) + User::After(20 * 1000); __KHEAP_MARKEND; gTest.Next(_L("Free kernel-side proxy IIC client")); @@ -1598,6 +1600,8 @@ gChanSlaveI2c.Close(); UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); +// Not safe to assume that heap clean-up has completed for the channels just closed, so insert a delay.(DEF145202) + User::After(20 * 1000); __KHEAP_MARKEND; gTest.Next(_L("Free kernel-side proxy IIC client")); diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/mediaext/d_nfe.cpp --- /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 +#include +#include +#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= 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 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; iDoCreate(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; iDelete(); + 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; iAttach(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; iiDfcQ,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; iiLocalDriveNum)); + + __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 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; iiTimerDfc.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; instanceiNfeDfcQ,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 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; instanceiDriver; + __ASSERT_ALWAYS(mediaDriver, NFE_FAULT()); + + if (swapDriveInfo == NULL) + swapDriveInfo = mediaDriver->GetSwapDrive(); + + for (TInt i=0; iiInfo.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; + } + + diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/mediaext/nfe.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mediaext/nfe.h Fri Apr 23 22:20:31 2010 +0100 @@ -0,0 +1,163 @@ +// 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\nfe.h +// +// + +#ifndef __NFE_H__ +#define __NFE_H__ + +#include + + + +// The following is stolen from the genuine NDE driver interface from nfe_interface.h +// >>>>>nfe_interface.h +enum TNfeCommands + { + ENfeDiskStatus = 0, // No longer used, preserved for SC/BC. + ENfeEncryptDisk = 1, + ENfeDecryptDisk = 2, + ENfeWipeDisk = 3, + // Debug commands below, enabled only in RnD compiled extension + ENfePause = 128, + ENfeContinue = 129, + }; + +enum TNfeDiskStatus + { + ENfeUnmounted = 0, + ENfeDecrypted = 8, + ENfeDecrypting = 9, + ENfeEncrypted = 10, + ENfeEncrypting = 11, + ENfeWiping = 12, + ENfeCorrupted = 13, + }; + + + +// The keys under the KNfeUID category are generated by combining the constants +// below with drive number by using the NFE_KEY macro below. +const TUint KNfeToThreadKey = 1; +const TUint KNfeToUiKey = 2; +const TUint KNfeToExtKey = 3; // No longer used, preserved for SC/BC. +const TUint KNfeProgressToUiKey = 4; +const TUint KNfeStatusToUiKey = 5; // Replaces ENfeDiskStatus command. + +//- Macros ------------------------------------------------------------------ +// Calculates pub&sub key for given drive and id. Top 8 bits are used for the +// drives. Bottom 8 bits are used for the ids. The rest of the bits are +// reserved and use zero value. The key layout: +// dddddddd0000000000000000kkkkkkkk +// ^bit 31 ^bit 0 +#define NFE_KEY(drive, id) (((drive) << 24) | (0xFF & (id))) +// <<< TNfeDeviceInfoBuf; + + +// Publish & Subscribe is used to initiate an encryption pass - to emulate the behaviour of the genuine NFE UI & driver +//const TUid KNfeUID = TUid::Uid(0xA000E7C5); // UID of NFE test mdia driver (D_NFE.MMP) +const TUid KNfeUID = {0x100039e3}; + + + + +#endif diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/mediaext/t_nfe.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mediaext/t_nfe.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -0,0 +1,406 @@ +// 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\t_nfe.cpp +// +// + +#define __E32TEST_EXTENSION__ + +#include +#include + + +RTest test(_L("t_nfe")); + +#include +#include +#include "nfe.h" + + +TBusLocalDrive Drive; +TBool TheWaitFlag = EFalse; // wait for drive to be encrypted before exiting test +TBool TheFinaliseDriveFlag = EFalse; +TBool TheDisplayStatusFlag = EFalse; // display drive status and then exit (i.e. don't encrypt) +TBool TheEncryptDriveFlag = ETrue; + +TInt FindNfeDrive(TInt aDriveNum) +/** +Find the next NFE drive + +@return Local drive identifier. +*/ + { + TInt drive = KErrNotFound; + +// test.Printf(_L("Searching for NFE drive:\n")); + + for (TInt i = aDriveNum; i < KMaxLocalDrives && drive < 0; ++i) + { + RLocalDrive d; + TBool change = EFalse; + + if(d.Connect(i, change) == KErrNone) + { +// test.Printf(_L("Connected to local drive %d\n"), i); + TLocalDriveCapsV4 dc; + TPckg capsPack(dc); + capsPack.FillZ(); + + if(d.Caps(capsPack) != KErrNone) + continue; + if (dc.iType == EMediaNANDFlash || dc.iType == EMediaHardDisk) + { + TNfeDeviceInfo nfeDeviceInfo; + TPtr8 nfeDeviceInfoBuf((TUint8*) &nfeDeviceInfo, sizeof(nfeDeviceInfo)); + nfeDeviceInfoBuf.FillZ(); + + TInt r = d.QueryDevice((RLocalDrive::TQueryDevice) EQueryNfeDeviceInfo, nfeDeviceInfoBuf); + +// test.Printf(_L("EQueryNfeDeviceInfo on local drive %d returned %d\n"), i, r); + if (r == KErrNone) + { + test.Printf(_L("\nFound NFE on local drive %d\n"), i); + drive = i; + } + } + d.Close(); + } + } + return drive; + } + + + +const TDesC* DriveStatus(TNfeDiskStatus aStatus) + { + _LIT(KNfeUnmounted, "Unmounted"); + _LIT(KNfeDecrypted, "Decrypted"); + _LIT(KNfeDecrypting, "Decrypting"); + _LIT(KNfeEncrypted, "Encrypted"); + _LIT(KNfeEncrypting, "Encrypting"); + _LIT(KNfeWiping, "Wiping"); + _LIT(KNfeCorrupted, "Corrupted"); + _LIT(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; + + } + } + +TInt DriveStatus(TInt aNfeDrive, TNfeDiskStatus& aStatus, TInt &aProgress) + { + TInt r = RProperty::Get( + KNfeUID, + NFE_KEY(aNfeDrive, KNfeStatusToUiKey), + *(TInt*) &aStatus); + if (r != KErrNone) + return r; + r = RProperty::Get( + KNfeUID, + NFE_KEY(aNfeDrive, KNfeProgressToUiKey), + *(TInt*) &aProgress); + return r; + } + +void DisplayNfeDeviceInfo(TInt aNfeDrive, TNfeDeviceInfo& aDeviceInfo) + { + test.Printf(_L("Stats: \n")); + + RLocalDrive d; + TBool change = EFalse; + TInt r = d.Connect(aNfeDrive, change); + test (r == KErrNone); + + TPtr8 nfeDeviceInfoBuf((TUint8*) &aDeviceInfo, sizeof(aDeviceInfo)); + nfeDeviceInfoBuf.FillZ(); + r = d.QueryDevice((RLocalDrive::TQueryDevice) EQueryNfeDeviceInfo, nfeDeviceInfoBuf); + test (r == KErrNone || r == KErrNotSupported); + + d.Close(); + + test.Printf(_L("iDriveCount %d\n"), aDeviceInfo.iDriveCount); + test.Printf(_L("iMediaSizeInBytes %lx\n"), aDeviceInfo.iMediaSizeInBytes); + + for (TInt i=0; i= 0 && di.iDriveLetter <= 25 ? di.iDriveLetter +'A' : '?'); + test.Printf(_L("iState %d\n"), di.Status()); + + test.Printf(_L("State = %S\n"), DriveStatus(di.Status())); + + test.Printf(_L("iEncryptStartPos %lx\n"), di.iEncryptStartPos); + test.Printf(_L("iEncryptEndPos %lx\n"), di.iEncryptEndPos); + test.Printf(_L("iPartitionBaseAddr %lx\n"), di.iEntry.iPartitionBaseAddr); + test.Printf(_L("iPartitionLen %lx\n"), di.iEntry.iPartitionLen); + test.Printf(_L("iPartitionType %x\n"), di.iEntry.iPartitionType); + + test.Printf(_L("iReadRequestCount %d\n"), di.iReadRequestCount); + test.Printf(_L("iWriteRequestCount %d\n"), di.iWriteRequestCount); + test.Printf(_L("iCodePagingRequesCount %d\n"), di.iCodePagingRequesCount); + test.Printf(_L("iDataPagingReadRequestCount %d\n"), di.iDataPagingReadRequestCount); + test.Printf(_L("iDataPagingWriteRequestCount %d\n"), di.iDataPagingWriteRequestCount); + test.Printf(_L("iUniqueID %08X\n"), di.iUniqueID); + } + } + +void EncryptDrive(TInt aNfeDrive) + { + // subscribe to cmd acknowledgement property - KNfeToUiKey + RProperty propToUi; + test.Printf(_L("Attaching ToUi property")); + TInt r = propToUi.Attach(KNfeUID,NFE_KEY(aNfeDrive,KNfeToUiKey)); + test.Printf(_L("Attaching returned %d"), r); + if (r != KErrNone) + return; + + + TRequestStatus status; + propToUi.Subscribe( status ); + + + // Issue command + test.Printf(_L("Encrypting drive %c...\n"), aNfeDrive+'A'); + r = RProperty::Set( + KNfeUID, + NFE_KEY(aNfeDrive, KNfeToThreadKey), + ENfeEncryptDisk); + test.Printf(_L("Encrypting drive %c, r %d\n"), aNfeDrive+'A', r); + test (r == KErrNone); + + // wait for ack + User::WaitForRequest( status ); + r = status.Int(); + test.Printf(_L("cmd status %d"), r); + test (r == KErrNone); + } + +void DecryptDrive(TInt aNfeDrive) + { + // subscribe to cmd acknowledgement property - KNfeToUiKey + RProperty propToUi; + test.Printf(_L("Attaching ToUi property")); + TInt r = propToUi.Attach(KNfeUID,NFE_KEY(aNfeDrive,KNfeToUiKey)); + test.Printf(_L("Attaching returned %d"), r); + if (r != KErrNone) + return; + + + TRequestStatus status; + propToUi.Subscribe( status ); + + + // Issue command + test.Printf(_L("Decrypting drive %c...\n"), aNfeDrive+'A'); + r = RProperty::Set( + KNfeUID, + NFE_KEY(aNfeDrive, KNfeToThreadKey), + ENfeDecryptDisk); + test.Printf(_L("Decrypting drive %c, r %d\n"), aNfeDrive+'A', r); + test (r == KErrNone); + + // wait for ack + User::WaitForRequest( status ); + r = status.Int(); + test.Printf(_L("cmd status %d"), r); + test (r == KErrNone); + } + +void WaitForFinish(TInt aNfeDrive, TBool aEncrypt) + { + TNfeDiskStatus diskStatus = ENfeCorrupted; + TInt progress = 0; + + TInt r = DriveStatus(aNfeDrive, diskStatus, progress); + test (r == KErrNone); + + // Poll progress status. + while (diskStatus != (aEncrypt ? ENfeEncrypted : ENfeDecrypted )) + { + r = DriveStatus(aNfeDrive, diskStatus, progress); + test (r == KErrNone); + test.Printf(_L("Drive %c, r %d progress %3u%% status %S\n"), aNfeDrive+'A', r, progress, DriveStatus((TNfeDiskStatus) diskStatus)); + + + if (TheFinaliseDriveFlag && progress > 10) + { + TheFinaliseDriveFlag = EFalse; + RFs fs; + TInt r = fs.Connect(); + test_KErrNone(r); + + r = fs.FinaliseDrive(aNfeDrive, RFs::EFinal_RW); + test_KErrNone(r); + return; + } + + User::After( 1000 * 500 ); + } + test.Printf( _L("\nFinished\n") ); + } + +// +// E32Main +// + +TInt ParseCommandArguments() + { + TInt tokenCount = 0; + TChar driveToTest = 'C';; + + TBuf<0x100> cmd; + User::CommandLine(cmd); + TLex lex(cmd); + + for (TPtrC token=lex.NextToken(); token.Length() != 0;token.Set(lex.NextToken())) + { + tokenCount++; + // Get the drive letter + if (tokenCount == 1) + { + TChar ch = token[0]; + if (ch.IsAlpha()) + { + if(token.Length() > 0) + { + driveToTest=token[0]; + driveToTest.UpperCase(); + } + } + RDebug::Print(_L("drive=%C"), (TUint) driveToTest); + continue; + } + + else if (token.CompareF(_L("-d")) == 0) + { + TheEncryptDriveFlag = EFalse; + } + else if (token.CompareF(_L("-e")) == 0) + { + TheEncryptDriveFlag = ETrue; + } + else if (token.CompareF(_L("-f")) == 0) + { + TheFinaliseDriveFlag = ETrue; + } + else if (token.CompareF(_L("-w")) == 0) + { + TheWaitFlag = ETrue; + } + else if (token.CompareF(_L("-s")) == 0) + { + TheDisplayStatusFlag = ETrue; + } + } + + return driveToTest; + } + +TInt E32Main() + { + test.Title(); + test.Start(_L("NFE tests")); + + RFs fs; + + TInt r = fs.Connect(); + test_KErrNone(r); + + TChar driveToTest = ParseCommandArguments(); + + TInt drive; + r = fs.CharToDrive(driveToTest,drive); + test_KErrNone(r); + + + TVolumeInfo volumeInfo; + r = fs.Volume(volumeInfo, drive); + test(r == KErrNone); + + + + TNfeDiskStatus diskStatus = ENfeCorrupted; + TInt progress = 0; + + r = DriveStatus(drive, diskStatus, progress); + test.Printf(_L("drive %c diskStatus %S, progress %d r %d\n"), drive+'A', DriveStatus(diskStatus), progress, r); + + if (TheDisplayStatusFlag) + { + test.Printf(_L("*** press any key ***")); + test.Getch(); + test.End(); + test.Close(); + return 0; + } + + if (r == KErrNone && diskStatus == ENfeDecrypted && TheEncryptDriveFlag) + { + test.Next(_L("Encrypting NFE drive")); + EncryptDrive(drive); + r = DriveStatus(drive, diskStatus, progress); + test.Printf(_L("drive %c diskStatus %S, progress %d r %d\n"), drive+'A', DriveStatus(diskStatus), progress, r); + } + + if (r == KErrNone && diskStatus == ENfeEncrypted && !TheEncryptDriveFlag) + { + test.Next(_L("Decrypting NFE drive")); + DecryptDrive(drive); + r = DriveStatus(drive, diskStatus, progress); + test.Printf(_L("drive %c diskStatus %S, progress %d r %d\n"), drive+'A', DriveStatus(diskStatus), progress, r); + } + + + if (r == KErrNone && TheWaitFlag) + { + test.Next(_L("Waiting for finish")); + WaitForFinish(drive, TheEncryptDriveFlag); + } + + + for(TInt nfeDrive = FindNfeDrive(0); nfeDrive != KErrNotFound; nfeDrive = FindNfeDrive(++nfeDrive)) + { + TNfeDeviceInfo deviceInfo; + DisplayNfeDeviceInfo(nfeDrive, deviceInfo); + } + + fs.Close(); + + test.End(); + test.Close(); + + return 0; + } + + diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/mediaext/t_nfe.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mediaext/t_nfe.mmp Fri Apr 23 22:20:31 2010 +0100 @@ -0,0 +1,33 @@ +// 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/group/t_nfe.mmp +// +// + +target t_nfe.exe +targettype exe + +capability All + +sourcepath ../mediaext +source t_nfe.cpp + +library euser.lib efsrv.lib + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + + + + +SMPSAFE diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/e32test/multimedia/t_sound2.cpp --- a/kerneltest/e32test/multimedia/t_sound2.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/e32test/multimedia/t_sound2.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -2379,6 +2379,10 @@ Test.Title(); Test.Start(_L("Load")); + // --- TEMPORARILY DISABLING T_SOUND2 + Test.Printf(_L("T_SOUND2 DISABLED UNTIL DEF144934 IS FIXED\n")); + CHECK(0); + // --- TEMPORARILY DISABLING T_SOUND2 if (Load()==KErrNotFound) { Test.Printf(_L("Shared chunk sound driver not supported - test skipped\r\n")); diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/demandpaging/t_nandpaging.cpp --- a/kerneltest/f32test/demandpaging/t_nandpaging.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/demandpaging/t_nandpaging.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -28,6 +28,7 @@ //! @SYMTestPriority High //! @SYMTestStatus Implemented +#define __E32TEST_EXTENSION__ #include RTest test(_L("T_NANDPAGING")); @@ -38,6 +39,7 @@ #include #include "testdefs.h" #include +#include "nfe.h" TInt DriveNumber=-1; // Parameter - Which drive? -1 = autodetect. @@ -544,9 +546,53 @@ return; } + // If the NFE test media driver extension is present, ALL the drive is encrypted; + // this means that there will be very few free blocks in the free block reservoir: this effectively + // disables background garbage collection and all block erasing needs to happen on the fly... + TNfeDeviceInfo nfeDeviceinfo; + TPtr8 nfeDeviceInfoBuf((TUint8*) &nfeDeviceinfo, sizeof(nfeDeviceinfo)); + nfeDeviceInfoBuf.FillZ(); + TInt r = Drive.QueryDevice((RLocalDrive::TQueryDevice) EQueryNfeDeviceInfo, nfeDeviceInfoBuf); +/* + if (r == KErrNone) + { + test.Printf(_L("NFE device detected, aborting garbage collection test for now\n")); + return; + } +*/ + // Create some free blocks by creating a huge file and then deleting it.... + if (r == KErrNone) + { + test.Printf(_L("NFE device detected\n")); + RFile file; + + TBuf<256> tempFileName = _L("?:\\f32-tst\\"); + tempFileName[0] = 'A'+DriveNumber; + + r = TheFs.MkDirAll(tempFileName); + test(r==KErrNone || r== KErrAlreadyExists); + + tempFileName+= _L("TEMP.TXT"); + + r = file.Replace(TheFs, tempFileName, EFileWrite); + test_KErrNone(r); + + for (TInt fileSize = KMaxTInt; fileSize > 0; fileSize >>= 1) + { + r = file.SetSize(fileSize); + test.Printf(_L("Setting file size to %d, r %d\n"), fileSize, r); + if (r == KErrNone) + break; + } + file.Close(); + r = TheFs.Delete(tempFileName); + test_KErrNone(r); + } + + + TInt timeout; TInt writesNeeded=100; - TInt r = KErrNone; RFile tempFile; TInt i; TInt ii; @@ -593,6 +639,7 @@ for (ii=0; ii0)); // ie, while garbage collection hasn't happened, or timed out diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp --- a/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -11,9 +11,11 @@ // Contributors: // // Description: -// f32test\scndrv\t_scn32dr1.cpp +// f32test\filesystem\fat\t_scn32dr1.cpp +// Tests that ScanDrive fixes known errors to a Rugged FAT drive // -// + +#define __E32TEST_EXTENSION__ #include #include @@ -262,10 +264,10 @@ { pos += BootSector.ReservedSectors() * BootSector.BytesPerSector(); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TPtr8 buf(&data[0], 4); r=TheRawDisk.Read(pos, buf); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); } @@ -290,7 +292,7 @@ return val; } -LOCAL_C void WriteFat(TInt aFatIndex,TInt aValue,const TUint8* aFat) +LOCAL_C void WriteToFatBuf(TInt aFatIndex,TInt aValue,const TUint8* aFat) // // Write a value to both fats starting at aFat // @@ -344,7 +346,7 @@ { TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum< name; name.Copy(d->Name()); RDebug::Print(_L("%5d: '%S' %S start %-5d size %d"), - aNum, &name, DirAttributes(d->Attributes()), d->StartCluster(), d->Size()); + aNum, &MakePrintable(name), DirAttributes(d->Attributes()), d->StartCluster(), d->Size()); } return ETrue; } @@ -696,12 +710,12 @@ if (aStart < 2 && gDiskType != EFat32) { HBufC8* buf=HBufC8::New(BootSector.RootDirEntries() * KSizeOfFatDirEntry); - test(buf != NULL); + test_NotNull(buf); TPtr8 ptr=buf->Des(); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r=TheRawDisk.Read(gRootDirStart, ptr); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); DumpRootDir(buf->Ptr()); delete(buf); @@ -712,12 +726,12 @@ if (GetFatEntry(cluster, aFat) != 0) { HBufC8* buf=HBufC8::New(gBytesPerCluster); - test(buf!=NULL); + test_NotNull(buf); TPtr8 ptr=buf->Des(); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r=TheRawDisk.Read(ClusterToByte(cluster), ptr); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster)); DumpDirCluster(ptr.Ptr()); @@ -786,12 +800,12 @@ // { HBufC8* buf=HBufC8::New(gBytesPerCluster*2); - test(buf!=NULL); + test_NotNull(buf); TPtr8 ptr=buf->Des(); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r=TheRawDisk.Read(ClusterToByte(aCluster), ptr); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); RDebug::Print(_L("Cluster %d @ 0x%08X:"), aCluster, ClusterToByte(aCluster)); TFatDirEntry* d = (TFatDirEntry*)ptr.Ptr() + aEntry; @@ -829,7 +843,7 @@ nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue); #endif - test(nRes == KErrNone); + test_KErrNone(nRes); } @@ -847,7 +861,7 @@ num[0] = TText(aDepth % 26 + 'A'); aDir+=num; r=TheFs.MkDir(aDir); - test(r==KErrNone); + test_KErrNone(r); } } @@ -860,7 +874,7 @@ while(aDepth--) { r=TheFs.RmDir(aDir); - test(r==KErrNone); + test_KErrNone(r); aDir.SetLength(aDir.Length()-2); } } @@ -877,7 +891,7 @@ aDir2=aDir1; aDir2+=_L("a\\"); TInt r=TheFs.MkDir(aDir2); - test(r==KErrNone); + test_KErrNone(r); // create dir with depth of 126 directories - one short of max depth CreateDeepDir(aDir1,101); // create dir with depth of 90 @@ -891,7 +905,7 @@ { DeleteDeepDir(aDir2,64); TInt r=TheFs.RmDir(aDir2); - test(r==KErrNone); + test_KErrNone(r); aDir2.SetLength(aDir2.Length()-2); DeleteDeepDir(aDir1,102); DeleteDeepDir(aDir1,24); @@ -925,7 +939,7 @@ aLong[len+1] = TText(count%26 + 'A'); count++; TInt r=temp.Create(TheFs,aLong,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); } } @@ -944,7 +958,7 @@ aLong[len+1] = TText(count%26 + 'A'); count++; TInt r=TheFs.Delete(aLong); - test(r==KErrNone || r==KErrNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound); } } @@ -966,7 +980,7 @@ name[2]=(TUint16)(count/26%26+'a'); name[3]=(TUint16)(count%26+'a'); r=TheFs.Delete(name); - test(r==KErrNone || r==KErrNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound); ++count; } } @@ -990,7 +1004,7 @@ name[2]=(TUint16)(count/26%26+'a'); name[3]=(TUint16)(count%26+'a'); r=f.Create(TheFs, name, EFileWrite); - test(r==KErrNone); + test_KErrNone(r); f.Close(); ++count; } @@ -1012,7 +1026,7 @@ dir[1]=(TUint16)(count/26+'a'); dir[2]=(TUint16)(count%26+'a'); r=TheFs.MkDir(dir); - test(r==KErrNone); + test_KErrNone(r); entriesSoFar+=2; ++count; } @@ -1032,7 +1046,7 @@ dir[1]=TUint16(count/26+'a'); dir[2]=TUint16(count%26+'a'); r=TheFs.RmDir(dir); - test(r==KErrNone); + test_KErrNone(r); entriesSoFar-=2; ++count; } @@ -1045,27 +1059,27 @@ { test.Next(_L("Delete Directory Structure")); TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\almostfull\\")); - test(r==KErrNone); + test_KErrNone(r); TInt entriesNeeded=(gEntriesPerCluster-2) / 2; //7*2entries + . + .. = full sector for (TInt i = 0; i < entriesNeeded; i++) { TFileName file=_L("\\scndrv\\dir2\\full\\__a"); file.AppendNum(i); r=TheFs.Delete(file); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); } r=TheFs.RmDir(_L("\\scndrv\\dir2\\full\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\scndrv\\dir2\\")); - test(r==KErrNone); + test_KErrNone(r); TFileName veryLongName=(_L("\\scndrv\\dir1\\")); MakeVeryLongName(veryLongName); r=TheFs.Delete(veryLongName); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\scndrv\\dir1\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\scndrv\\")); - test(r==KErrNone); + test_KErrNone(r); } LOCAL_C void CreateDirectoryStructure() @@ -1076,34 +1090,34 @@ test.Next(_L("Create Directory Structure")); // cluster 3 (root dir is cluster 2) TInt r=TheFs.MkDir(_L("\\scndrv\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 4 r=TheFs.MkDir(_L("\\scndrv\\dir1\\")); - test(r==KErrNone); + test_KErrNone(r); TFileName veryLongName=(_L("\\scndrv\\dir1\\")); MakeVeryLongName(veryLongName); RFile f; // cluster 5 r=f.Create(TheFs,veryLongName,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=f.SetSize(512); - test(r==KErrNone); + test_KErrNone(r); f.Close(); // cluster 6 r=TheFs.MkDir(_L("\\scndrv\\dir2\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 7 r=TheFs.MkDir(_L("\\scndrv\\dir2\\full\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 8 r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedirwith3entries\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 9 r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedir2with3entries\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 10 r=TheFs.MkDir(_L("\\scndrv\\dir2\\almostfull\\")); - test(r==KErrNone); + test_KErrNone(r); // cluster 11-17 TInt entriesNeeded=(gEntriesPerCluster-2) / 2; //7*2entries + . + .. = full sector for (TInt i = 0; i < entriesNeeded; i++) @@ -1112,11 +1126,11 @@ file.AppendNum(i); LastInFull = file; r=f.Create(TheFs,file,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); if (i < 7) { r=f.SetSize(512); - test(r==KErrNone); + test_KErrNone(r); } f.Close(); } @@ -1132,14 +1146,14 @@ file1.AppendNum(1); file2.AppendNum(2); r=f.Create(TheFs,file1,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=f.SetSize(512); - test(r==KErrNone); + test_KErrNone(r); f.Close(); r=f.Create(TheFs,file2,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=f.SetSize(512); - test(r==KErrNone); + test_KErrNone(r); f.Close(); } @@ -1165,16 +1179,16 @@ // contains aOffset ExtBufLen = 2 * gBytesPerCluster; ExtBufPtr = HBufC8::New(ExtBufLen); - test(ExtBufPtr != NULL); + test_NotNull(ExtBufPtr); // read the clusters in ExtBufAdd = aOffset - aOffset % gBytesPerCluster; TInt clust = (ExtBufAdd - (gDataStartBytes - gRootDirStart)) /gBytesPerCluster + 2; RDebug::Print(_L("Extension buffer for cluster %d allocated"), clust); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TPtr8 des(ExtBufPtr->Des()); r=TheRawDisk.Read(gRootDirStart + ExtBufAdd, des); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); } // convert to offset in the extension buffer @@ -1209,10 +1223,10 @@ // reads directory section of disk into buffer // { - test(aCluster != 1); + test_Value(aCluster, aCluster != 1); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); if (aCluster == -1) // all clusters ? { @@ -1233,7 +1247,7 @@ r=TheRawDisk.Read(gRootDirStart + pos, dirPtr); } - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); } @@ -1243,21 +1257,21 @@ // { TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r=TheRawDisk.Read(gFatStartBytes, aFatBuf); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); } -LOCAL_C void WriteDirDisk(TDes8& aDirBuf, TInt aCluster = -1) +LOCAL_C void WriteDirEntryToDisk(TDes8& aDirBuf, TInt aCluster = -1) // -// writes dir buffer to disk +// writes dir entry buffer to disk // { - test(aCluster != 1); + test_Value(aCluster, aCluster != 1); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); if (aCluster == -1) { @@ -1278,29 +1292,29 @@ r=TheRawDisk.Write(gRootDirStart + pos, dirPtr); } - test(r==KErrNone); + test_KErrNone(r); if (ExtBufPtr) { TPtr8 des(ExtBufPtr->Des()); r=TheRawDisk.Write(gRootDirStart + ExtBufAdd, des); - test(r==KErrNone); + test_KErrNone(r); } TheRawDisk.Close(); } -LOCAL_C void WriteFatDisk(TDes8& aFatBuf, TInt aStart=0) +LOCAL_C void WriteFatToDisk(TDes8& aFatBuf, TInt aStart=0) // // writes fat buffer to disk // { TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TInt fatCount=BootSector.NumberOfFats() - aStart; TInt pos = gFatStartBytes + aStart * gFatSizeSectors*BootSector.BytesPerSector(); while(fatCount--) { r=TheRawDisk.Write(pos, aFatBuf); - test(r==KErrNone); + test_KErrNone(r); pos += gFatSizeSectors*BootSector.BytesPerSector(); } TheRawDisk.Close(); @@ -1357,15 +1371,15 @@ gFatTestEntries = KMaxFatSize; gFatTestSize = PosInBytes(gFatTestEntries); FatBufPtr=HBufC8::New(gFatTestSize); - test(FatBufPtr!=NULL); + test_NotNull(FatBufPtr); DirBufPtr=HBufC8::New(DirBufferSize()); - test(DirBufPtr!=NULL); + test_NotNull(DirBufPtr); // Buffers for reading from disk FatDiskPtr=HBufC8::New(gFatTestSize); - test(FatDiskPtr!=NULL); + test_NotNull(FatDiskPtr); DirDiskPtr=HBufC8::New(DirBufferSize()); - test(DirDiskPtr!=NULL); + test_NotNull(DirDiskPtr); } LOCAL_C TBool IsSameAsDrive(const TDes8& aFatBuf,const TDes8& aDirBuf) @@ -1452,12 +1466,12 @@ else if (ExtBufPtr) { HBufC8* extPtr = HBufC8::New(ExtBufLen); - test(extPtr != NULL); + test_NotNull(extPtr); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TPtr8 des(extPtr->Des()); r=TheRawDisk.Read(ExtBufAdd+gRootDirStart, des); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); TInt i = FindUnMatch(ExtBufPtr->Ptr(), extPtr->Ptr(), ExtBufLen); if (i >= 0) @@ -1506,7 +1520,7 @@ if(aAddEOfDir) WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry); TPtr8 dirBuf=DirBufPtr->Des(); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); } LOCAL_C TBool TestPartialEntry(TEntryInfo aEntry) @@ -1516,7 +1530,7 @@ { test.Next(_L("TestPartialEntry")); TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); WriteDelete(aEntry.iBytePos,aEntry.iLength); TPtr8 fatBuf=FatBufPtr->Des(); @@ -1539,7 +1553,7 @@ if(aAddEOfDir) WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry); TPtr8 dirBuf=DirBufPtr->Des(); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); } LOCAL_C TBool TestMatchingEntry(TEntryInfo aToDelete) @@ -1550,7 +1564,7 @@ test.Next(_L("TestMatchingEntries")); WriteDelete(aToDelete.iBytePos,aToDelete.iLength); TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TPtr8 fatBuf=FatBufPtr->Des(); TPtr8 dirBuf=DirBufPtr->Des(); @@ -1574,8 +1588,8 @@ CDir* dirs; // check no entries in the root directory TInt r=TheFs.GetDir(KRoot,KEntryAttMaskSupported,ESortNone,dirs); - test(r==KErrNone); - test(dirs->Count()==0); + test_KErrNone(r); + test_Equal(0,dirs->Count()); delete(dirs); dirs=NULL; @@ -1593,13 +1607,13 @@ RFile file; r=file.Replace(TheFs,TestFileName,EFileShareExclusive); - test(r==KErrNone); + test_KErrNone(r); file.Close(); // get short name TFileName shortName; r=TheFs.GetShortName(TestFileName,shortName); - test(r==KErrNone); + test_KErrNone(r); test(shortName==KOrigShortName); // must be first entry in root, modify to read like @@ -1608,26 +1622,26 @@ TInt bytePos=ClusterEntryToBytes(0,1); RRawDisk raw; r=raw.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TBuf8<1> buf(1); //-- change 2nd character in the short name (Fat DOS entry) buf[0]=(TUint8)'\xC4'; r=raw.Write(gRootDirStart+bytePos+1,buf); - test(r==KErrNone); + test_KErrNone(r); //-- fix the fiddled short name checksum in the corresponding VFat entry bytePos=ClusterEntryToBytes(0,0); buf[0]=(TUint8)0x2f; r=raw.Write(gRootDirStart+bytePos+13,buf); - test(r==KErrNone); + test_KErrNone(r); // retrieve short name from media. // Note: do not use RFs::GetShortName() as its behaviours are code page dependent. bytePos=ClusterEntryToBytes(0,1); TBuf8<11> shortNameBuf8; r=raw.Read(gRootDirStart+bytePos,shortNameBuf8); - test(r==KErrNone); + test_KErrNone(r); shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8); shortName.Copy(shortNameBuf8); raw.Close(); @@ -1638,15 +1652,15 @@ //TheFs.SetDebugRegister(KFSYS); r=TheFs.ScanDrive(gSessionPath); TheFs.SetDebugRegister(0); - test(r==KErrNone); + test_KErrNone(r); DumpData(NULL, 0, 20); // retrieve short name from media. r=raw.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); bytePos=ClusterEntryToBytes(0,1); r=raw.Read(gRootDirStart+bytePos,shortNameBuf8); - test(r==KErrNone); + test_KErrNone(r); shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8); shortName.Copy(shortNameBuf8); raw.Close(); @@ -1655,7 +1669,7 @@ // delete file r=TheFs.Delete(TestFileName); - test(r==KErrNone); + test_KErrNone(r); } LOCAL_C void TestMountAndScan() @@ -1668,46 +1682,47 @@ test.Next(_L("TestMountAndScan")); HBufC8* newFat=HBufC8::New(gFatTestSize); - test(newFat!=NULL); + test_NotNull(newFat); TPtr8 fat=newFat->Des(); TPtr8 origFat=FatBufPtr->Des(); TPtr8 origDir=DirBufPtr->Des(); // set cluster of \scndrv\dir1\ to a hanging cluster ReadFatDisk(fat); - WriteFat(gClusterDir1ext,35,fat.Ptr()); - WriteFat(35,36,fat.Ptr()); - WriteFatDisk(fat); + WriteToFatBuf(gClusterDir1ext,35,fat.Ptr()); + WriteToFatBuf(35,36,fat.Ptr()); + WriteFatToDisk(fat); // set the default path to something other than the current drive TFileName fsName; TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TFileName origDefPath, newDefPath; r=TheFs.SessionPath(origDefPath); - test(r==KErrNone); + test_KErrNone(r); newDefPath=origDefPath; newDefPath[0]=(TText)'z'; r=TheFs.SetSessionPath(newDefPath); - test(r==KErrNone); + test_KErrNone(r); r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0); if (r == KErrNone) { primaryExtensionExists = ETrue; } r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); // mount file system and check scandrive corrects error TBool isMount; if (primaryExtensionExists) r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount); else r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount); - test(isMount && r==KErrNone); + test(isMount); + test_KErrNone(r); TBool res=IsSameAsDrive(origFat,origDir); test(res); r=TheFs.SetSessionPath(origDefPath); - test(r==KErrNone); + test_KErrNone(r); delete newFat; } @@ -1721,14 +1736,14 @@ TBool primaryExtensionExists = EFalse; TFileName fsName; TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0); if (r == KErrNone) { primaryExtensionExists = ETrue; } r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); // RFs::MountFileSystemAndScan twice consecutively // first time @@ -1737,15 +1752,37 @@ r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount); else r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount); - test(isMount && r==KErrNone); + test(isMount); + test_KErrNone(r); // and a second time if (primaryExtensionExists) r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount); else r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount); - test(!isMount && r==KErrAccessDenied); + test(!isMount); + test_Equal(KErrAccessDenied,r); } + +static void CreateContiguousClusterChain(TUint32 aStartIndex, TUint32 aEndIndex, const TUint8* aFatPtr, TBool aMarkEoc) +/* + * Creates a contiguous cluster chain in the FAT buffer. + * + * @param aStartIndex The first cluster index of the chain + * aEndIndex The last cluster index of the chain + * aFatPtr FAT table buffer pointer + * aMarkEoc If ETrue, aEndIndex will be marked as EOC, else it will be a hanging cluster chain + */ + { + // Write cluster chain + for(TUint i=aStartIndex; iDes(); TPtr8 origFat=FatBufPtr->Des(); TPtr8 origDir=DirBufPtr->Des(); - // set cluster of \scndrv\dir1\ to a hanging cluster + // Set cluster of \scndrv\dir1\ to hanging cluster chain test.Start(_L("Test hanging cluster in \\scndrv\\dir1\\")); ReadFatDisk(fat); - WriteFat(gClusterDir1ext,35,fat.Ptr()); - WriteFat(35,36,fat.Ptr()); - WriteFatDisk(fat); + WriteToFatBuf(gClusterDir1ext,35,fat.Ptr()); + WriteToFatBuf(35,36,fat.Ptr()); + WriteFatToDisk(fat); // gClusterDir1ext->35->36 TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TBool res=IsSameAsDrive(origFat,origDir); test(res); - // set cluster chain of first entry of \scndrv\dir1\ to + // Set cluster chain of first entry of \scndrv\dir1\ to // larger size than file size test.Next(_L("Test hanging cluster in first entry")); ReadFatDisk(fat); - WriteFat(gClusterDir1ext,39,fat.Ptr()); - WriteFat(39,500,fat.Ptr()); - WriteFat(500,gEndOfChain,fat.Ptr()); - WriteFatDisk(fat); + WriteToFatBuf(gClusterDir1ext,39,fat.Ptr()); + WriteToFatBuf(39,500,fat.Ptr()); + CreateContiguousClusterChain(500, 505, fat.Ptr(), ETrue); + WriteFatToDisk(fat); // gClusterDir1ext->39->500->501->502->503->504->505->EOC r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(origFat,origDir); test(res); - // set cluster of \scndrv\ to a hanging cluster + // Set cluster of \scndrv\ to a hanging cluster test.Next(_L("Test hanging cluster of \\scndrv\\")); ReadFatDisk(fat); - WriteFat(gClusterScnDrv,511,fat.Ptr()); - WriteFatDisk(fat); + WriteToFatBuf(gClusterScnDrv,511,fat.Ptr()); + WriteFatToDisk(fat); // gClusterScnDrv->511 r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(origFat,origDir); test(res); @@ -1803,7 +1840,7 @@ { test.Next(_L("Check lost clusters")); HBufC8* newFat=HBufC8::New(gFatTestSize); - test(newFat!=NULL); + test_NotNull(newFat); TPtr8 fat=newFat->Des(); TPtr8 origFat=FatBufPtr->Des(); TPtr8 origDir=DirBufPtr->Des(); @@ -1813,12 +1850,10 @@ // write cluster chain test.Start(_L("Test removal of lost cluster chain")); ReadFatDisk(fat); - for(TInt i=25;i<35;++i) - WriteFat(i,i+1,fat.Ptr()); - WriteFat(35,gEndOfChain,fat.Ptr()); - WriteFatDisk(fat); + CreateContiguousClusterChain(25, 35, fat.Ptr(), ETrue); + WriteFatToDisk(fat); // 25->26->27->28->29->30->31->32->33->34->35->EOC TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TBool res=IsSameAsDrive(origFat,origDir); test(res); @@ -1829,17 +1864,17 @@ TInt off = j*BootSector.BytesPerSector()+j*7%512; fat[off]=1; } - WriteFatDisk(fat); + WriteFatToDisk(fat); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(origFat,origDir); test(res); // write semi-random changes to second fat test.Next(_L("Test semi-random changes to second fat")); - WriteFatDisk(fat, 1); + WriteFatToDisk(fat, 1); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(origFat,origDir); test(res); @@ -1847,6 +1882,74 @@ test.End(); } + +static void DoHangingAndLostClusters() +/* + * Tests that ScanDrive fixes MULTIPLE hanging clusters and removes lost clusters. + * It creates multiple hanging and lost cluster chains in the FAT table and + * expects ScanDrive to fix them all. + */ + { + test.Start(_L("Check multiple hanging and lost cluster chains")); + HBufC8* newFat = HBufC8::New(gFatTestSize); + test_NotNull(newFat); + TPtr8 fat = newFat->Des(); + TPtr8 origFat = FatBufPtr->Des(); + TPtr8 origDir = DirBufPtr->Des(); + ReadFatDisk(origFat); + ReadDirDisk(origDir); + + test.Printf(_L("Create multiple hanging cluster chains\n")); + ReadFatDisk(fat); + // Set hanging cluster for the file in \scndrv\dir1 + // gClusterDir1ext+1->25->26->27->28->29->30->31->32->33->34->35 + WriteToFatBuf(gClusterDir1ext+1, 25, fat.Ptr()); + CreateContiguousClusterChain(25, 35, fat.Ptr(), EFalse); + // Set hanging cluster for the first file in \scndrv\dir2 + // gClusterDir2_AFull+1->249->250->53->54->55->EOC + WriteToFatBuf(gClusterDir2_AFull+1, 249, fat.Ptr()); + WriteToFatBuf(249, 250, fat.Ptr()); + WriteToFatBuf(250, 53, fat.Ptr()); + CreateContiguousClusterChain(53, 55, fat.Ptr(), ETrue); + // Set hanging cluster for the fourth file in \scndrv\dir2 + // gClusterDir2_AFull+4->59->60->61->62->63 + WriteToFatBuf(gClusterDir2_AFull+4, 59, fat.Ptr()); + CreateContiguousClusterChain(59, 63, fat.Ptr(), EFalse); + // Set hanging cluster for the second file in \scndrv\dir2 + // gClusterDir2_AFull+2->67->68->69->EOC + WriteToFatBuf(gClusterDir2_AFull+2, 67, fat.Ptr()); + CreateContiguousClusterChain(67, 69, fat.Ptr(), ETrue); + + test.Printf(_L("Create multiple lost clusters\n")); + // Create 1st lost cluster chain (clusters 36-45) + CreateContiguousClusterChain(36, 45, fat.Ptr(), ETrue); + // Create 2nd lost cluster chain (clusters 246-248,56-58) + CreateContiguousClusterChain(246, 248, fat.Ptr(), EFalse); + WriteToFatBuf(248, 56, fat.Ptr()); + CreateContiguousClusterChain(56, 58, fat.Ptr(), ETrue); + // Create 3rd lost cluster chain (clusters 251-253,564-566, with hanging end) + CreateContiguousClusterChain(251, 253, fat.Ptr(), EFalse); + WriteToFatBuf(253, 564, fat.Ptr()); + CreateContiguousClusterChain(564, 566, fat.Ptr(), EFalse); + + // Flush all FAT changes to the media + WriteFatToDisk(fat); + + test.Next(_L("Test ScanDrive fixes multiple hanging and lost cluster chains")); + TInt r = TheFs.CheckDisk(gSessionPath); // CheckDisk should detect an error + test_Value(r, r != KErrNone); + r = TheFs.ScanDrive(gSessionPath); // ScanDrive should find the errors and fix them + test_KErrNone(r); + r = TheFs.CheckDisk(gSessionPath); + test_KErrNone(r); + TBool res = IsSameAsDrive(origFat, origDir); + test(res); + + delete newFat; + test.End(); + } + + LOCAL_C void DoPartEntries() // // Tests that scandrive detects/corrects partial entries @@ -1860,9 +1963,9 @@ TPtr8 dirBuf=DirBufPtr->Des(); TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedirwith3entries\\")); - test(r==KErrNone || r==KErrNotFound || KErrPathNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound || r==KErrPathNotFound); r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedir2with3entries\\")); - test(r==KErrNone || r==KErrNotFound || KErrPathNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound || r==KErrPathNotFound); if (BootSector.RootDirEntries() != 0) { @@ -1871,7 +1974,7 @@ test.Next(_L("Partial entry at end of rootdir")); FillUpRootDir(2); r=temp.Create(TheFs,_L("\\temp"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); ReadDirDisk(dirBuf); ReadFatDisk(fatBuf); @@ -1891,7 +1994,7 @@ CreatePartialEntry(partial2,3,EFalse); // entry has been allocated a cluster which scandrive should delete along with partial entry if (last > 0) - WriteFat(last,0,fatBuf.Ptr()); + WriteToFatBuf(last,0,fatBuf.Ptr()); res=TestPartialEntry(partial2); test(res); @@ -1899,26 +2002,26 @@ test.Next(_L("Test directory reclaim")); last = GetStartCluster(gClusterDir2_Full,gEntriesPerCluster-2); WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2)); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); TInt entry = GetFatEntry(gClusterDir2_Full, fatBuf.Ptr()); - WriteFat(gClusterDir2_Full,gEndOfChain,fatBuf.Ptr()); + WriteToFatBuf(gClusterDir2_Full,gEndOfChain,fatBuf.Ptr()); while (entry && (entry & gEndOfChain) != gEndOfChain) { TInt next = GetFatEntry(entry, fatBuf.Ptr()); - WriteFat(entry,0,fatBuf.Ptr()); + WriteToFatBuf(entry,0,fatBuf.Ptr()); entry = next; } if (last > 0) - WriteFat(last,0,fatBuf.Ptr()); + WriteToFatBuf(last,0,fatBuf.Ptr()); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(fatBuf,dirBuf); test(res); // use last entry of first cluster in \scndrv\dir2\full\ test.Next(_L("Partial entry at end of subdir")); r=temp.Create(TheFs,_L("\\scndrv\\dir2\\full\\temp"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); ReadDirDisk(dirBuf); ReadFatDisk(fatBuf); @@ -1931,12 +2034,12 @@ test.Next(_L("Partial entry preceeding end-of-dir marker")); last = GetStartCluster(gClusterDir2_AFull,14); if (last > 0) - WriteFat(last,0,fatBuf.Ptr()); + WriteToFatBuf(last,0,fatBuf.Ptr()); last = GetStartCluster(gClusterDir2_AFull,8); if (last > 0) - WriteFat(last,0,fatBuf.Ptr()); + WriteToFatBuf(last,0,fatBuf.Ptr()); WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_AFull,14)); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); TEntryInfo partial4(ClusterEntryToBytes(gClusterDir2_AFull,8),6); CreatePartialEntry(partial4,4,EFalse); res=TestPartialEntry(partial4); @@ -1952,14 +2055,14 @@ // create entry in \scndrv\dir2\almostfull\ // test.Next(_L("Partial entry with invalid dos name")); // r=temp.Create(TheFs,_L("\\scndrv\\dir2\\almostfull\\Dodgy file name"),EFileShareAny); -// test(r==KErrNone); +// test_KErrNone(r); // temp.Close(); // ReadDirDisk(dirBuf); // TInt dosStart=ClusterEntryToBytes(gClusterDir2_AFull,4); // dirBuf[dosStart+4]=0x1; // WriteDirDisk(dirBuf); // r=TheFs.ScanDrive(gSessionPath); -// test(r==KErrNone); +// test_KErrNone(r); // WriteDelete(dosStart-2*32,3); // res=IsSameAsDrive(fatBuf,dirBuf); // test(res); @@ -1971,26 +2074,26 @@ last = GetStartCluster(gClusterDir2_Full,gEntriesPerCluster-1); WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2)); WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-1)); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); TFileName longFile=_L("\\scndrv\\dir2\\full\\"); MakeVeryLongName(longFile); r=temp.Create(TheFs,longFile,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); ReadDirDisk(dirBuf); - WriteFat(gClusterDir2_Full,gClusterDir2_SD3E,fatBuf.Ptr()); - WriteFat(gClusterDir2_SD3E,gClusterDir2_SD23E,fatBuf.Ptr()); - WriteFat(gClusterDir2_SD23E,gEndOfChain,fatBuf.Ptr()); + WriteToFatBuf(gClusterDir2_Full,gClusterDir2_SD3E,fatBuf.Ptr()); + WriteToFatBuf(gClusterDir2_SD3E,gClusterDir2_SD23E,fatBuf.Ptr()); + WriteToFatBuf(gClusterDir2_SD23E,gEndOfChain,fatBuf.Ptr()); if (last > 0) - WriteFat(last,0,fatBuf.Ptr()); + WriteToFatBuf(last,0,fatBuf.Ptr()); TEntryInfo partial5(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),19); CreatePartialEntry(partial5,7,EFalse); res=TestPartialEntry(partial5); test(res); r=TheFs.Delete(longFile); - test(r==KErrNone || r==KErrNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound); r=TheFs.Delete(_L("\\temp")); - test(r==KErrNone || r==KErrNotFound); + test_Value(r, r==KErrNone || r==KErrNotFound); } ReadDirDisk(dirBuf); @@ -2040,16 +2143,16 @@ test.Next(_L("matching entries in same subdir")); // delete entries to allow contiguous clusters in \scndrv\dir2\full directory TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedirwith3entries\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedir2with3entries\\")); - test(r==KErrNone); + test_KErrNone(r); // ensure directory is expanded RFile temp; r=temp.Create(TheFs,_L("\\scndrv\\dir2\\full\\temp"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); r=TheFs.Delete(_L("\\scndrv\\dir2\\full\\temp")); - test(r==KErrNone); + test_KErrNone(r); ReadDirDisk(dirBuf); ReadFatDisk(fatBuf); TEntryInfo from4(ClusterEntryToBytes(gClusterDir2_Full,4),2); @@ -2062,14 +2165,14 @@ test.Next(_L("matching entries in diff dirs + new cluster")); // delete last entry in directory r=TheFs.Delete(LastInFull); - test(r==KErrNone); + test_KErrNone(r); TFileName veryLongName=_L("\\scndrv\\dir2\\full\\"); MakeVeryLongName(veryLongName); r=temp.Create(TheFs,veryLongName,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); temp.Close(); r=TheFs.Delete(veryLongName); - test(r==KErrNone); + test_KErrNone(r); ReadDirDisk(dirBuf); ReadFatDisk(fatBuf); TEntryInfo from5(ClusterEntryToBytes(gClusterDir1,2),19); @@ -2099,7 +2202,7 @@ ReadFatDisk(fatBuf); // run scandisk and compare TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TBool res=IsSameAsDrive(fatBuf,dirBuf); test(res); // Create a entry with matching start cluster and check fixed up @@ -2126,7 +2229,7 @@ ReadFatDisk(fatBuf); TInt r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TBool res=IsSameAsDrive(fatBuf,dirBuf); test(res); @@ -2219,9 +2322,9 @@ name.AppendNumFixedWidth(i+totalFilesCreated, EHex, 3); RFile f; r = f.Create(TheFs, name, EFileShareAny); - test(r == KErrNone); + test_KErrNone(r); r = f.Write(buf); - test(r == KErrNone); + test_KErrNone(r); f.Close(); } @@ -2254,7 +2357,7 @@ } - WriteDirDisk(dirBuf, cluster); + WriteDirEntryToDisk(dirBuf, cluster); totalFilesCreated += filesThisTime; test.Printf(_L(" created %d entries\n"), totalFilesCreated); } @@ -2266,7 +2369,7 @@ test.Printf(_L("Running ScanDrive\n"), filesThisTime); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TBool res=IsSameAsDrive(fatBuf,dirBuf); test(res); @@ -2278,17 +2381,17 @@ name.Append(_L("tempfile.")); name.AppendNumFixedWidth(i, EHex, 3); r = TheFs.Delete(name); - test(r == KErrNone); + test_KErrNone(r); } ReadDirDisk(dirBuf); ReadFatDisk(fatBuf); WriteEndOfDir(ClusterEntryToBytes(cluster, startEntry)); - WriteDirDisk(dirBuf); + WriteDirEntryToDisk(dirBuf); test.Printf(_L("Running ScanDrive\n"), filesThisTime); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); res=IsSameAsDrive(fatBuf,dirBuf); test(res); } @@ -2329,6 +2432,7 @@ DoPartEntries(); DoLostClusters(); DoHangingClusters(); + DoHangingAndLostClusters(); TestMountAndScan(); TestConsecutiveMountAndScans(); DeleteDirectoryStructure(); @@ -2350,7 +2454,7 @@ { TInt r; r = TheFs.CharToDrive(gSessionPath[0], gDriveNumber); - test( KErrNone == r ); + test_KErrNone(r); //-- set up console output @@ -2368,7 +2472,7 @@ // check this is not the internal ram drive TVolumeInfo v; r=TheFs.Volume(v); - test(r==KErrNone); + test_KErrNone(r); if(v.iDrive.iMediaAtt&KMediaAttVariableSize) { test.Printf(_L("Error: Internal ram drive not tested\n")); @@ -2376,7 +2480,7 @@ } r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); DoTests(); diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/filesystem/fat/t_tscan32.cpp --- a/kerneltest/f32test/filesystem/fat/t_tscan32.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/filesystem/fat/t_tscan32.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -11,9 +11,10 @@ // Contributors: // // Description: -// f32test\scndrv\t_tscan32.cpp +// f32test\filesystem\fat\t_tscan32.cpp // -// + +#define __E32TEST_EXTENSION__ #include #include @@ -36,9 +37,9 @@ #ifdef _DEBUG GLREF_D RTest test; -GLDEF_D TInt TheFunctionNumber; -GLDEF_D TInt TheOpNumber; -GLDEF_D TInt TheFailCount; +GLDEF_D TInt TheFunctionNumber; // Indicates which test to run +GLDEF_D TInt TheOpNumber; // Indicates which file operation to be tested +GLDEF_D TInt TheFailCount; GLDEF_D TBool IsReset; GLDEF_D TFileName TestExeName=_L("?:\\T_SCANDR.EXE"); //Renaming it to fit in one root dir entry. GLDEF_D TFileName LogFileName=_L("?:\\T_SCANDR.LOG"); //Renaming it to fit in one root dir entry. @@ -56,8 +57,8 @@ const TInt KDirAttrLongMask = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive; const TInt KDirLastLongEntry = 0x40; -GLDEF_D TInt WriteFailValue; - +GLDEF_D TInt WriteFailValue; // Indicates what error should return from a write failure + // Value assigned in t_scn32dr2 and t_scn32dr3 LOCAL_C TFatBootSector BootSector; LOCAL_D RRawDisk TheRawDisk; @@ -79,7 +80,13 @@ LOCAL_D HBufC8* gFatBuf = NULL; LOCAL_D TInt gFatAddr = -1; -enum TFatChain {EChainStd,EChainAlternate,EChainBackwards,EChainForwards}; +enum TFatChain + { + EChainStd, // Cluster chain grows contiguously + EChainAlternate, // Cluster chain grows forward but not contiguously + EChainBackwards, // Cluster chain first goes backwards(up to 3.5kb for fat16 file) and then forwards + EChainForwards // Cluster chain first goes forward (upto 3.5kb for fat16 file) and then backwards + }; LOCAL_C TBool IsInternalRam() // @@ -88,7 +95,7 @@ { TVolumeInfo v; TInt r=TheFs.Volume(v,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); return(v.iDrive.iMediaAtt&KMediaAttVariableSize); } @@ -102,10 +109,10 @@ TInt r=log.Open(TheFs,LogFileName,EFileShareExclusive|EFileWrite); if(r!=KErrNone) test.Printf(_L("error=%d\n"),r); - test(r==KErrNone); + test_KErrNone(r); TInt size; r=log.Size(size); - test(r==KErrNone); + test_KErrNone(r); TBuf8<16> buf; buf.SetLength(4); buf[0]=(TUint8)TheFunctionNumber; @@ -113,7 +120,7 @@ buf[2]=(TUint8)TheFailCount; buf[3]='\n'; r=log.Write(size,buf,buf.Length()); - test(r==KErrNone); + test_KErrNone(r); test.Printf(_L("Written func=%d,op=%d,fail=%d\n"),TheFunctionNumber,TheOpNumber,TheFailCount); log.Close(); } @@ -141,8 +148,8 @@ TInt r=log.Open(TheFs,LogFileName,EFileShareExclusive); if(r!=KErrNone) test.Printf(_L("error in ReadLogFile()=%d\n"),r); - test(r==KErrNone); - test(r==KErrNone); + test_KErrNone(r); + TInt fileSize; r=log.Size(fileSize); if(fileSize==0) @@ -187,7 +194,7 @@ */ static void DoZeroFillMedia(TInt64 aStartPos, TInt64 aEndPos, RRawDisk& aWriter) { - test(aStartPos >=0 && aEndPos >=0 && aStartPos < aEndPos); + test(aStartPos >=0 && aEndPos >=0 && aStartPos < aEndPos); if(aStartPos == aEndPos) return; @@ -198,7 +205,7 @@ const TUint32 KBufSz=65536*2; //-- buffer with zeroes nRes = buf.CreateMax(KBufSz); - test(nRes == KErrNone); + test_KErrNone(nRes); buf.FillZ(); @@ -209,7 +216,7 @@ TPtrC8 ptr(buf.Ptr(), bytesToWrite); nRes = aWriter.Write(aStartPos, ptr); - test(nRes == KErrNone || nRes == KErrDiskFull); + test_Value(nRes, nRes == KErrNone || nRes == KErrDiskFull); aStartPos+=bytesToWrite; rem-=bytesToWrite; @@ -227,7 +234,7 @@ { TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); TUint32 startPos = gDataStartBytes; if (gDiskType == EFat32) @@ -269,7 +276,7 @@ { TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<= gFatAddr + gBytesPerCluster) { TPtr8 ptr=gFatBuf->Des(); - TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); + test_KErrNone(r); r=TheRawDisk.Read(pos, ptr); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); gFatAddr = pos; } @@ -550,6 +557,18 @@ aName.SetLength(i); } +TDes& MakePrintable(TDes& aDes) + { + TInt len = aDes.Length(); + + for (TInt i=0; i name; name.Copy(d->Name()); RDebug::Print(_L("%5d: '%S' %S cluster %d"), - aNum, &name, DirAttributes(d->Attributes()), d->StartCluster()); + aNum, &MakePrintable(name), DirAttributes(d->Attributes()), d->StartCluster()); } return ETrue; } @@ -619,12 +638,12 @@ if (GetFatEntry(cluster, aFat) != 0) { HBufC8* buf=HBufC8::New(gBytesPerCluster); - test(buf!=NULL); + test_NotNull(buf); TPtr8 ptr=buf->Des(); TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A'); - test(r==KErrNone); + test_KErrNone(r); r=TheRawDisk.Read(ClusterToByte(cluster), ptr); - test(r==KErrNone); + test_KErrNone(r); TheRawDisk.Close(); RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster)); DumpDirCluster(ptr.Ptr()); @@ -708,7 +727,7 @@ dir[1]=TUint16(count/26+'a'); dir[2]=TUint16(count%26+'a'); r=TheFs.MkDir(dir); - test(r==KErrNone); + test_KErrNone(r); entriesSoFar+=2; ++count; } @@ -733,7 +752,7 @@ dir[1]=TUint16(count/26+'a'); dir[2]=TUint16(count%26+'a'); r=TheFs.RmDir(dir); - test(r==KErrNone); + test_KErrNone(r); entriesSoFar-=2; ++count; } @@ -755,7 +774,7 @@ { TEntry entry; TInt r=TheFs.Entry(aName,entry); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); return(r==KErrNone?(TBool)ETrue:(TBool)EFalse); } @@ -794,7 +813,7 @@ // { TInt r=TheFs.Entry(aName,aEntry); - test(r==KErrNone); + test_KErrNone(r); } LOCAL_C TBool IsSameEntryDetails(TEntry aOldEntry,TEntry aNewEntry) @@ -817,9 +836,9 @@ TInt size1,size2; size1=size2=0; TInt r=file1.Create(TheFs,aNameOne,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=file2.Create(TheFs,aNameTwo,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); // one entry for file1 for every 40 entries for file2 // if file 1 subseqently deleted then 7 entries available // in that fat sector - ~3.5kb file size - for fat16 @@ -831,15 +850,15 @@ { size1+=gBytesPerCluster; r=file1.SetSize(size1); - test(r==KErrNone); + test_KErrNone(r); first=EFalse; --entries; } else { size2+=gBytesPerCluster*ratio; - r=file1.SetSize(size1); - test(r==KErrNone); + r=file2.SetSize(size2); + test_KErrNone(r); first=ETrue; entries-=ratio; } @@ -892,7 +911,7 @@ TFileName fullName(aName); fullName.Append(fn); TInt r = TheFs.Delete(fullName); - test(r == KErrNone); + test_KErrNone(r); entry += 1 + (fn.Length() + 12) / 13; } RDebug::Print(_L("CleanDirectory(%S, %d)"), &aName, aClusters); @@ -927,7 +946,7 @@ fullName.Append(fn); RFile file; TInt r = file.Create(TheFs,fullName,EFileShareAny); - test(r == KErrNone); + test_KErrNone(r); file.Close(); entry += 1 + (fn.Length() + 12) / 13; } @@ -942,7 +961,7 @@ // { TInt r=TheFs.Delete(_L("\\fat\\file2")); - test(r==KErrNone||KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(aIsDir) return(TheFs.RmDir(aName)); else @@ -956,7 +975,7 @@ // { TInt r=DeleteAlternateEntry(aName,aIsDir); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); RFile file; if(aIsDir) { @@ -970,17 +989,17 @@ if(r!=KErrNone) return(r); r=file.SetSize(1); //ensure file allocated a start cluster - test(r==KErrNone); + test_KErrNone(r); } CreateAlternate(_L("\\fat\\file1"),_L("\\fat\\file2")); r=TheFs.Delete(_L("\\fat\\file1")); - test(r==KErrNone); + test_KErrNone(r); if(aIsDir) ExpandDirectory(aName,aSize); else { r=file.SetSize(aSize); - test(r==KErrNone); + test_KErrNone(r); file.Close(); } return(KErrNone); @@ -992,11 +1011,11 @@ // { TInt r=TheFs.Delete(_L("\\fat\\file2")); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); r=TheFs.Delete(_L("\\fat\\file4")); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); r=TheFs.Delete(_L("\\fat\\file5")); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(aIsDir) r=TheFs.RmDir(aName); else @@ -1011,16 +1030,16 @@ // { TInt r=DeleteForwardEntry(aName,aIsDir); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); RFile file1,file2,entry; r=file1.Create(TheFs,_L("\\fat\\file1"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=file1.SetSize(EntriesPerFatSector()*gBytesPerCluster); - test(r==KErrNone); + test_KErrNone(r); r=file2.Create(TheFs,_L("\\fat\\file2"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=file2.SetSize(EntriesPerFatSector()*gBytesPerCluster); - test(r==KErrNone); + test_KErrNone(r); if(aIsDir) { r=TheFs.MkDir(aName); @@ -1033,27 +1052,27 @@ if(r!=KErrNone) return(r); r=entry.SetSize(1); // ensure entry has start cluster allocated - test(r==KErrNone); + test_KErrNone(r); } CreateAlternate(_L("\\fat\\file3"),_L("\\fat\\file4")); RFile file5; r=file5.Create(TheFs,_L("\\fat\\file5"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=file5.SetSize(EntriesPerFatSector()*gBytesPerCluster*2); - test(r==KErrNone); + test_KErrNone(r); file1.Close(); file2.Close(); file5.Close(); r=TheFs.Delete(_L("\\fat\\file1")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Delete(_L("\\fat\\file3")); - test(r==KErrNone); + test_KErrNone(r); if(aIsDir) ExpandDirectory(aName,aSize); else { r=entry.SetSize(aSize); - test(r==KErrNone); + test_KErrNone(r); entry.Close(); } return(KErrNone); @@ -1065,9 +1084,9 @@ // { TInt r=TheFs.Delete(_L("\\fat\\file2")); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); r=TheFs.Delete(_L("\\fat\\file3")); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(aIsDir) r=TheFs.RmDir(aName); else @@ -1082,7 +1101,7 @@ // { TInt r=DeleteBackwardEntry(aName,aIsDir); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); CreateAlternate(_L("\\fat\\file1"),_L("\\fat\\file2")); RFile entry; if(aIsDir) @@ -1097,22 +1116,22 @@ if(r!=KErrNone) return(r); r=entry.SetSize(1); - test(r==KErrNone); + test_KErrNone(r); } RFile file3; r=file3.Create(TheFs,_L("\\fat\\file3"),EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); r=file3.SetSize(EntriesPerFatSector()*gBytesPerCluster); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Delete(_L("\\fat\\file1")); - test(r==KErrNone); + test_KErrNone(r); file3.Close(); if(aIsDir) ExpandDirectory(aName,aSize); else { r=entry.SetSize(aSize); - test(r==KErrNone); + test_KErrNone(r); entry.Close(); } return(KErrNone); @@ -1135,7 +1154,7 @@ // { TInt r=DeleteStdEntry(aName,aIsDir); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(aIsDir) { r=TheFs.MkDir(aName); @@ -1150,12 +1169,12 @@ if(r==KErrNone) { r=file.SetSize(aSize); - test(r==KErrNone); + test_KErrNone(r); } else if(r==KErrAlreadyExists) { TInt res =file.Open(TheFs,aName,EFileShareAny); - test(res==KErrNone); + test_KErrNone(res); } else return(r); @@ -1206,28 +1225,28 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Delete(aName); if(r==KErrNone) break; - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(!EntryExists(aName)); ++TheOpNumber; TheFailCount=0; @@ -1262,18 +1281,18 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aName,ETrue,aChain,aDirSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(aName); if(r==KErrNone) break; - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); RDebug::Print(_L("%6d: ScanDrive = %d"), __LINE__, r); if (r != KErrNone) @@ -1282,16 +1301,16 @@ DumpFat(); DumpData(NULL, 0, 200); } - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); RDebug::Print(_L("%6d: CheckDisk = %d"), __LINE__, r); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(!EntryExists(aName)); ++TheOpNumber; TheFailCount=0; @@ -1309,31 +1328,31 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=DeleteEntry(aName,ETrue,EChainStd); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.MkDir(aName); if(r==KErrNone) break; - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aName)); r=DeleteEntry(aName,ETrue,EChainStd); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1351,9 +1370,9 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aOldName,aIsDir,aChain,aSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); r=DeleteEntry(aNewName,aIsDir,aChain); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); GetEntryDetails(aOldName,oldEntryInfo); if(IsReset) { @@ -1361,34 +1380,29 @@ WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Rename(aOldName,aNewName); if(r==KErrNone) break; - if(r!=WriteFailValue) - { - test.Printf(_L("r=%d\n"),r); - test(EFalse); - } - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); // no start cluster if aSize==0 if(aSize!=0) test(OneEntryExists(aOldName,aNewName)); ++failCount; } r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aNewName) && !EntryExists(aOldName)); GetEntryDetails(aNewName,newEntryInfo); test(IsSameEntryDetails(oldEntryInfo,newEntryInfo)); r=DeleteEntry(aNewName,aIsDir,aChain); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1410,16 +1424,16 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aOldName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); if(aBothExist) { r=CreateEntry(aNewName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); } else { r=DeleteEntry(aNewName,EFalse,aChain); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); } GetEntryDetails(aOldName,oldEntryInfo); if(IsReset) @@ -1428,15 +1442,15 @@ WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Replace(aOldName,aNewName); if(r==KErrNone) break; - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); if(!aBothExist && aFileSize!=0) test(OneEntryExists(aOldName,aNewName)); else if(aBothExist) @@ -1444,14 +1458,14 @@ ++failCount; } r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aNewName) && !EntryExists(aOldName)); GetEntryDetails(aNewName,newEntryInfo); test(IsSameEntryDetails(oldEntryInfo,newEntryInfo)); r=DeleteEntry(aNewName,EFalse,aChain); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1468,35 +1482,35 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=DeleteEntry(aName,EFalse,EChainStd); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Create(TheFs,aName,EFileShareAny); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aName)); r=DeleteEntry(aName,EFalse,EChainStd); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1519,28 +1533,28 @@ WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Temp(TheFs,aPath,temp,EFileShareAny); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } test(r==WriteFailValue); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(temp)); r=DeleteEntry(temp,EFalse,EChainStd); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1558,9 +1572,9 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aOldName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); r=DeleteEntry(aNewName,EFalse,aChain); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); GetEntryDetails(aOldName,oldEntryInfo); if(IsReset) { @@ -1569,34 +1583,34 @@ } RFile file; r=file.Open(TheFs,aOldName,EFileShareExclusive|EFileWrite); - test(r==KErrNone); + test_KErrNone(r); r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); r=file.Rename(aNewName); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); file.Close(); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); if(aFileSize) test(OneEntryExists(aOldName,aNewName)); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aNewName) && !EntryExists(aOldName)); GetEntryDetails(aNewName,newEntryInfo); test(IsSameEntryDetails(oldEntryInfo,newEntryInfo)); r=DeleteEntry(aNewName,EFalse,aChain); - test(r==KErrNone); + test_KErrNone(r); ++TheOpNumber; TheFailCount=0; } @@ -1615,12 +1629,12 @@ if(aAlreadyExists) { r=CreateEntry(aName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); } else { r=DeleteEntry(aName,EFalse,aChain); - test(r==KErrNone||r==KErrNotFound); + test_Value(r, r==KErrNone||r==KErrNotFound); } if(IsReset) { @@ -1628,28 +1642,28 @@ WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Replace(TheFs,aName,EFileShareAny); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); test(EntryExists(aName)); r=DeleteEntry(aName,EFalse,aChain); - test(r==KErrNone); + test_KErrNone(r); if(!aAlreadyExists) { ++TheOpNumber; @@ -1675,54 +1689,54 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aName,EFalse,aChain,aOldFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Open(TheFs,aName,EFileShareAny|EFileWrite); - test(r==KErrNone); + test_KErrNone(r); r=file.SetSize(aNewFileSize); // close the file before testing the return value! file.Close(); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } file.Close(); - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=file.Open(TheFs,aName,EFileShareAny|EFileWrite); - test(r==KErrNone); + test_KErrNone(r); TInt size; r=file.Size(size); - test(r==KErrNone); - test(size==aNewFileSize||size==aOldFileSize); + test_KErrNone(r); + test_Value(size, size==aNewFileSize||size==aOldFileSize); file.Close(); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Open(TheFs,aName,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); TInt fileSize; r=file.Size(fileSize); - test(r==KErrNone); - test(aNewFileSize==fileSize); + test_KErrNone(r); + test_Equal(aNewFileSize,fileSize); file.Close(); r=DeleteEntry(aName,EFalse,aChain); - test(r==KErrNone); + test_KErrNone(r); ++TheFunctionNumber; TheFailCount=0; } @@ -1739,7 +1753,7 @@ TInt newSize=(aFileSize>=aPos+aLength)?aFileSize:aPos+aLength; HBufC8* desPtr; desPtr=HBufC8::New(aLength); - test(desPtr!=NULL); + test_NotNull(desPtr); TPtr8 des=desPtr->Des(); des.SetLength(aLength); InitialiseWriteBuffer(des); @@ -1747,64 +1761,64 @@ { test.Printf(_L("failCount=%d\n"),failCount); r=CreateEntry(aName,EFalse,aChain,aFileSize); - test(r==KErrNone||r==KErrAlreadyExists); + test_Value(r, r==KErrNone||r==KErrAlreadyExists); if(IsReset) { ++TheFailCount; WriteLogFile(); } r=SetWriteFailOn(failCount); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Open(TheFs,aName,EFileShareAny|EFileWrite); - test(r==KErrNone); + test_KErrNone(r); r=file.Write(aPos,des,aLength); if(r==KErrNone) { r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff); - test(r==KErrNone); + test_KErrNone(r); file.Close(); break; } - test(r==WriteFailValue); + test_Equal(WriteFailValue,r); file.Close(); r=TheFs.ScanDrive(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); file.Open(TheFs,aName,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); TInt fileSize; r=file.Size(fileSize); // with fair scheduling enabled it's possible for the file // size to grow even if the write appears to have failed... -// test(fileSize==aFileSize||fileSize==newSize); - test(fileSize>=aFileSize && fileSize <= newSize); +// test_Value(fileSize, fileSize==aFileSize||fileSize==newSize); + test_Value(fileSize, fileSize>=aFileSize && fileSize <= newSize); file.Close(); ++failCount; } r=TheFs.CheckDisk(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Open(TheFs,aName,EFileShareAny); - test(r==KErrNone); + test_KErrNone(r); TInt fileSize; r=file.Size(fileSize); - test(r==KErrNone); - test(newSize==fileSize); + test_KErrNone(r); + test_Equal(newSize,fileSize); HBufC8* desPtr2; desPtr2=HBufC8::New(aLength); - test(desPtr2!=NULL); + test_NotNull(desPtr2); TPtr8 des2=desPtr2->Des(); des2.SetLength(aLength); r=file.Read(aPos,des2,des2.Length()); - test(r==KErrNone); + test_KErrNone(r); r=des2.Compare(des); - test(r==0); + test_KErrNone(r); file.Close(); r=DeleteEntry(aName,EFalse,aChain); - test(r==KErrNone); + test_KErrNone(r); delete desPtr; delete desPtr2; ++TheFunctionNumber; @@ -1973,7 +1987,7 @@ ClearDiskData(); r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); switch(TheFunctionNumber) { @@ -1981,15 +1995,15 @@ case(1):{ TestOperation1(); r=TheFs.MkDir(_L("\\fat\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.MkDir(_L("\\test\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.MkDir(_L("\\ANother\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.MkDir(_L("\\test\\subdir1\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.MkDir(_L("\\test\\subdir2\\")); - test(r==KErrNone);} + test_KErrNone(r);} case(2):{ TestOperation2(); // add some filler files @@ -2037,15 +2051,15 @@ DeleteEntry(_L("\\test\\subdir1\\FillerTwo"),EFalse,EChainStd); DeleteEntry(_L("\\test\\subdir1\\FillerOne"),EFalse,EChainStd); r=TheFs.RmDir(_L("\\test\\subdir2\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\test\\subdir1\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\ANother\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\test\\")); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\fat\\")); - test(r==KErrNone); + test_KErrNone(r); if (gFatBuf) { delete gFatBuf; diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/group/bld.inf --- a/kerneltest/f32test/group/bld.inf Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/group/bld.inf Fri Apr 23 22:20:31 2010 +0100 @@ -31,6 +31,8 @@ ../../../userlibandfileserver/fileserver/inc/runtests.h /epoc32/include/ PRJ_TESTMMPFILES +../../e32test/mediaext/t_nfe + // These tests must be run early on so they do not time out on LFFS disks. #ifdef WINS @@ -259,6 +261,7 @@ t_plugin_v2beta.mmp t_localtime + #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API t_file64bit manual fhserver64bit support diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/group/t_nandpaging.mmp --- a/kerneltest/f32test/group/t_nandpaging.mmp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/group/t_nandpaging.mmp Fri Apr 23 22:20:31 2010 +0100 @@ -17,6 +17,7 @@ TARGET t_nandpaging.exe TARGETTYPE EXE +userinclude ../../e32test/mediaext SOURCEPATH ../demandpaging SOURCE t_nandpaging.cpp LIBRARY euser.lib efsrv.lib hal.lib diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/group/wintest.bat --- a/kerneltest/f32test/group/wintest.bat Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/group/wintest.bat Fri Apr 23 22:20:31 2010 +0100 @@ -175,6 +175,7 @@ echo FlashResumeTime 0 >>%EPOCROOT%epoc32\data\epoc.ini echo FlashWriteTime 0 >>%EPOCROOT%epoc32\data\epoc.ini echo NandDriverType=XSR >>%EPOCROOT%epoc32\data\epoc.ini + echo MediaExtensionDriver=?medtestnfe.pdd >>%EPOCROOT%epoc32\data\epoc.ini if exist %BASEPATH%e32\rombuild\platsec.settings ( type %BASEPATH%e32\rombuild\platsec.settings >>%EPOCROOT%epoc32\data\epoc.ini ) else ( diff -r 70ba09fd07a5 -r fc55edbf3919 kerneltest/f32test/server/t_misc.cpp --- a/kerneltest/f32test/server/t_misc.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/kerneltest/f32test/server/t_misc.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -15,10 +15,16 @@ // // +#define __E32TEST_EXTENSION__ #include #include #include "t_server.h" +// If there is an NFE media driver present, then because of the way EDeleteNotify requests work, +// the data retrieved from a deleted file will not be a buffer full of zero's, but instead a buffer +// full of decrypted zero's +#define __NFE_MEDIA_DRIVER_PRESENT__ + #ifdef __VC32__ // Solve compilation problem caused by non-English locale #pragma setlocale("english") @@ -26,6 +32,8 @@ GLDEF_D RTest test(_L("T_MISC")); +const TUint KBufLength = 0x100; + LOCAL_C void Test1() // // Open, write to and read from a file @@ -34,19 +42,19 @@ test.Next(_L("Open, write to and read from a file")); TInt r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Create(TheFs,_L("Hello.Wld"),EFileWrite); - test(r==KErrNone); + test_KErrNone(r); r=file.Write(_L8("Hello World"),11); - test(r==KErrNone); + test_KErrNone(r); file.Close(); r=file.Open(TheFs,_L("Hello.Wld"),EFileRead); - test(r==KErrNone); + test_KErrNone(r); TBuf8<256> buf; r=file.Read(buf); - test(r==KErrNone); + test_KErrNone(r); test(buf==_L8("Hello World")); file.Close(); } @@ -59,17 +67,17 @@ test.Next(_L("Open and read from a file")); TInt r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); RFile file; r=file.Open(TheFs,_L("Hello.Wld"),EFileRead); - test(r==KErrNone); + test_KErrNone(r); TBuf8<256> buf; r=file.Read(buf); - test(r==KErrNone); + test_KErrNone(r); test(buf==_L8("Hello World")); file.Close(); r=TheFs.Delete(_L("HELLO.WLD")); - test(r==KErrNone); + test_KErrNone(r); } LOCAL_C void Test3() @@ -80,25 +88,25 @@ test.Next(_L("Create nested directories")); TInt r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TheFs.ResourceCountMarkStart(); // r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\A.B")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\RIGHT\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); // r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\ONE\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\TWO\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\THREE\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\TWO\\BOTTOM\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); // r=TheFs.MkDirAll(_L("\\F32-TST\\RIGHT\\TOP\\MID\\BOT\\")); - test(r==KErrNone || r==KErrAlreadyExists); + test_Value(r, r == KErrNone || r==KErrAlreadyExists); } LOCAL_C void Test4() @@ -109,58 +117,58 @@ test.Next(_L("Test returned error values")); TInt r=TheFs.SetSessionPath(gSessionPath); - test(r==KErrNone); + test_KErrNone(r); TheFs.ResourceCountMarkStart(); // r=TheFs.MkDir(_L("\\")); - test(r==KErrAlreadyExists); + test_Value(r, r == KErrAlreadyExists); r=TheFs.MkDir(_L("\\LEFT")); - test(r==KErrAlreadyExists); + test_Value(r, r == KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\")); - test(r==KErrAlreadyExists); + test_Value(r, r == KErrAlreadyExists); r=TheFs.MkDir(_L("\\F32-TST\\LEFT\\..\\NEWDIR\\")); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); r=TheFs.MkDir(_L("\\F32-TST\\NEWDIR\\SUBDIR\\")); - test(r==KErrPathNotFound); + test_Value(r, r == KErrPathNotFound); // r=TheFs.RmDir(_L("\\")); - test(r==KErrInUse); + test_Value(r, r == KErrInUse); r=TheFs.RmDir(_L("\\PROG")); - test(r==KErrInUse); + test_Value(r, r == KErrInUse); r=TheFs.RmDir(_L("\\F32-TST\\")); - test(r==KErrInUse); + test_Value(r, r == KErrInUse); RDir dir; r=dir.Open(TheFs,_L("V:\\asdf"),KEntryAttNormal); - test(r==KErrNone || r==KErrNotReady || r==KErrNotFound); + test_Value(r, r == KErrNone || r==KErrNotReady || r==KErrNotFound); if (r==KErrNone) dir.Close(); r=dir.Open(TheFs,_L("L:\\asdf"),KEntryAttNormal); - test(r==KErrNone || r==KErrNotReady || r==KErrNotFound); + test_Value(r, r == KErrNone || r==KErrNotReady || r==KErrNotFound); dir.Close(); // TEntry entry; r=TheFs.Entry(_L("z:\\NOTEXiSTS\\file.txt"),entry); - test(r==KErrPathNotFound); + test_Value(r, r == KErrPathNotFound); r=TheFs.Entry(_L("z:\\NOTEXiSTS\\"),entry); - test(r==KErrNotFound); + test_Value(r, r == KErrNotFound); r=TheFs.Entry(_L("z:\\SYSTEM\\"),entry); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Entry(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin)?_L("z:\\SYS\\BIN\\ESHELL.EXE"):_L("z:\\SYSTEM\\BIN\\ESHELL.EXE"),entry); - test(r==KErrNone); + test_KErrNone(r); r=dir.Open(TheFs,_L("\\*"),NULL); - test(r==KErrNone); + test_KErrNone(r); TEntry dirEntry; r=dir.Read(dirEntry); - test(r==KErrNone || r==KErrEof); + test_Value(r, r == KErrNone || r==KErrEof); if (r==KErrNone) test.Printf(_L("%S\n"),&dirEntry.iName); dir.Close(); r=dir.Open(TheFs,_L("A:\\*"),NULL); - test(r==KErrNotReady || r==KErrNone); + test_Value(r, r == KErrNotReady || r==KErrNone); dir.Close(); } @@ -181,13 +189,13 @@ { RFile f; r=f.Open(TheFs,KTFileCpp,EFileRead); - test(r==KErrNone); + test_KErrNone(r); r=f.Seek(ESeekAddress,pos); TText8* ptrPos=*(TText8**)&pos; - test(r==KErrNone); + test_KErrNone(r); TBuf8<1024> readBuf; r=f.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); TPtrC8 memBuf(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -195,10 +203,10 @@ ptrPos+=9913; pos=9913; r=f.Seek(ESeekStart,pos); - test(r==KErrNone); + test_KErrNone(r); readBuf.SetLength(0); r=f.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); memBuf.Set(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -207,16 +215,16 @@ pos=10; r=f2.Open(TheFs,KTFsrvCpp,EFileRead); - test(r==KErrNone); + test_KErrNone(r); r=f2.Seek(ESeekAddress,pos); ptrPos=*(TText8**)&pos; - test(r==KErrNone); + test_KErrNone(r); readBuf.SetLength(0); pos=10; r=f2.Seek(ESeekStart,pos); - test(r==KErrNone); + test_KErrNone(r); r=f2.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); memBuf.Set(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -224,10 +232,10 @@ ptrPos+=2445; pos=10+2445; r=f2.Seek(ESeekStart,pos); - test(r==KErrNone); + test_KErrNone(r); readBuf.SetLength(0); r=f2.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); memBuf.Set(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -235,13 +243,13 @@ pos=0; r=f.Seek(ESeekAddress,pos); ptrPos=*(TText8**)&pos; - test(r==KErrNone); + test_KErrNone(r); readBuf.SetLength(0); pos=0; r=f.Seek(ESeekStart,pos); - test(r==KErrNone); + test_KErrNone(r); r=f.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); memBuf.Set(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -249,10 +257,10 @@ ptrPos+=5245; pos=5245; r=f.Seek(ESeekStart,pos); - test(r==KErrNone); + test_KErrNone(r); readBuf.SetLength(0); r=f.Read(readBuf); - test(r==KErrNone); + test_KErrNone(r); test(readBuf.Length()==readBuf.MaxLength()); memBuf.Set(ptrPos,readBuf.Length()); test(memBuf==readBuf); @@ -271,14 +279,14 @@ RFile f; TInt r=f.Replace(TheFs,_L("Z:\\Test\\T_Fsrv.Cpp"),EFileRead); - test(r==KErrAccessDenied); + test_Value(r, r == KErrAccessDenied); r=f.Create(TheFs,_L("Z:\\Test\\newT_Fsrv.Cpp"),EFileRead); - test(r==KErrAccessDenied); + test_Value(r, r == KErrAccessDenied); r=f.Open(TheFs,_L("Z:\\Test\\T_Fsrv.Cpp"),EFileRead); - test(r==KErrNone); + test_KErrNone(r); f.Close(); r=f.Open(TheFs,_L("Z:\\Test\\T_Fsrv.Cpp"),EFileRead|EFileWrite); - test(r==KErrAccessDenied); + test_Value(r, r == KErrAccessDenied); } LOCAL_C void Test7() @@ -295,7 +303,7 @@ TEntry entry; TInt r=TheFs.Entry(file1,entry); - test(r==KErrNone); + test_KErrNone(r); test(entry.iType==uid1); TUidType uid2(TUid::Uid(4),TUid::Uid(5),TUid::Uid(6)); @@ -303,19 +311,19 @@ TPtrC8 uidData((TUint8*)&checkedUid,sizeof(TCheckedUid)); RFile f; r=f.Open(TheFs,file1,EFileRead|EFileWrite); - test(r==KErrNone); + test_KErrNone(r); r=f.Write(uidData); - test(r==KErrNone); + test_KErrNone(r); r = f.Flush(); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.Entry(file1,entry); - test(r==KErrNone); + test_KErrNone(r); test(entry.iType==uid2); f.Close(); r=TheFs.Entry(file1,entry); - test(r==KErrNone); + test_KErrNone(r); test(entry.iType==uid2); } @@ -538,7 +546,7 @@ CFileMan* fMan=CFileMan::NewL(TheFs); TInt r=fMan->Copy(_L("Z:\\TEST\\T_FILE.CPP"),_L("C:\\T_FILE.CPP")); - test(r==KErrNone || r==KErrAccessDenied); + test_Value(r, r == KErrNone || r==KErrAccessDenied); delete fMan; TUint8* addr=TheFs.IsFileInRom(_L("C:\\ESHELL.EXE")); test(addr==NULL); @@ -567,7 +575,7 @@ for(i=0;i drive17=_L("Flibble"); TBuf<64> drive25=_L("RAMDRIVE"); TInt r=TheFs.SetDriveName(0,drive0); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(4,drive4); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(17,drive17); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(25,drive25); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.GetDriveName(0,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive0); r=TheFs.GetDriveName(4,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive4); r=TheFs.GetDriveName(17,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive17); r=TheFs.GetDriveName(25,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive25); drive0=_L("askdjflsdfourewoqiuroiuaksjdvx,cvsdhwjhjhalsjhfshfkjhslj"); r=TheFs.SetDriveName(0,drive0); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.GetDriveName(0,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive0); // Test with illegal characters in drive name @@ -612,13 +620,13 @@ drive25=_L("RAMD//RIVE"); r=TheFs.SetDriveName(0,drive0); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); r=TheFs.SetDriveName(4,drive4); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); r=TheFs.SetDriveName(17,drive17); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); r=TheFs.SetDriveName(25,drive25); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); // Test that it is OK to set the name to no characters @@ -628,25 +636,25 @@ drive25=_L(""); r=TheFs.SetDriveName(0,drive0); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(4,drive4); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(17,drive17); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.SetDriveName(25,drive25); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.GetDriveName(0,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive0); r=TheFs.GetDriveName(4,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive4); r=TheFs.GetDriveName(17,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive17); r=TheFs.GetDriveName(25,driveName); - test(r==KErrNone); + test_KErrNone(r); test(driveName==drive25); @@ -662,11 +670,11 @@ TVolumeInfo vol; TInt r=TheFs.Volume(vol); test.Printf(_L("VolumeName = %S\n"),&vol.iName); - test(r==KErrNone); + test_KErrNone(r); r=TheFs.RmDir(_L("\\asdfasdf.\\")); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); r=TheFs.MkDir(_L("\\asdfasdf.\\")); - test(r==KErrBadName); + test_Value(r, r == KErrBadName); } LOCAL_C void Test12() @@ -697,23 +705,23 @@ test.Next(_L("Test RFs::Volume")); TVolumeInfo vol; TInt r=TheFs.Volume(vol,EDriveB); - test(r==KErrNotReady || r==KErrNone || KErrPathNotFound); + test_Value(r, r == KErrNotReady || r==KErrNone || r == KErrPathNotFound); test.Printf(_L("RFs::Volume EDriveB returned %d\n"),r); r=TheFs.Volume(vol,EDriveC); - test(r==KErrNotReady || r==KErrNone || KErrPathNotFound); + test_Value(r, r == KErrNotReady || r==KErrNone || r == KErrPathNotFound); test.Printf(_L("RFs::Volume EDriveC returned %d\n"),r); r=TheFs.Volume(vol,EDriveD); - test(r==KErrNotReady || r==KErrNone || KErrPathNotFound); + test_Value(r, r == KErrNotReady || r==KErrNone || r == KErrPathNotFound); test.Printf(_L("RFs::Volume EDriveD returned %d\n"),r); r=TheFs.Volume(vol,EDriveE); - test(r==KErrNotReady || r==KErrNone || KErrPathNotFound); + test_Value(r, r == KErrNotReady || r==KErrNone || r == KErrPathNotFound); test.Printf(_L("RFs::Volume EDriveE returned %d\n"),r); r=TheFs.Volume(vol,EDriveF); - test(r==KErrNotReady || r==KErrNone || KErrPathNotFound); + test_Value(r, r == KErrNotReady || r==KErrNone || r == KErrPathNotFound); test.Printf(_L("RFs::Volume EDriveF returned %d\n"),r); } @@ -722,7 +730,9 @@ TInt CreateStuffedFile(RFs& aFs, const TDesC& aFileName, TUint aFileSize); TInt CreateEmptyFile(RFs& aFs, const TDesC& aFileName, TUint aFileSize); TBool CheckFileContents(RFs& aFs, const TDesC& aFileName); +#ifndef __NFE_MEDIA_DRIVER_PRESENT__ TBool CheckBufferContents(const TDesC8& aBuffer, TUint aPrintBaseAddr=0); +#endif /** Testing unallocated data initialization vulnerability in RFile @@ -740,7 +750,7 @@ //-- 1. get drives list nRes=TheFs.DriveList(driveList); - test(nRes == KErrNone); + test_KErrNone(nRes); //-- 2. walk through all drives, performing the test only on suitable ones for (TInt drvNum=0; drvNum buffer; buffer.SetLength(KBufLength); @@ -1289,13 +1300,12 @@ TInt nRes = KErrNone; RFile file; - const TInt KBufLength = 0x100; TBuf8 buffer; buffer.SetLength(0); //-- open the file nRes = file.Open(aFs, aFileName, EFileRead); - test(nRes == KErrNone); + test_KErrNone(nRes); //-- check file contents TUint nFilePos=0; @@ -1303,7 +1313,7 @@ { //-- read data from the file into the buffer nRes = file.Read(buffer); - test(nRes == KErrNone); + test_KErrNone(nRes); if(buffer.Length() == 0) { @@ -1311,6 +1321,18 @@ break; //EOF } +#ifdef __NFE_MEDIA_DRIVER_PRESENT__ + // check the buffer doesn't contain the same pattern written to it by CreateStuffedFile() + TUint i; + for(i = 0; i < KBufLength; i++) + if (buffer[i] != static_cast (i)) + break; + if (i == KBufLength) + { + nRes = KErrCorrupt; //-- indicate that the read buffer contains illegitimate information + break; //-- comment this out if you need a full dump of the file + } +#else //-- check if the buffer contains only allowed data (RAM page initialisation data, etc. e.g. 0x00, 0xff, 0x03, 0xcc) if(!CheckBufferContents(buffer, nFilePos)) { @@ -1318,6 +1340,7 @@ nRes = KErrCorrupt; //-- indicate that the read buffer contains illegitimate information break; //-- comment this out if you need a full dump of the file } +#endif nFilePos+=buffer.Length(); } diff -r 70ba09fd07a5 -r fc55edbf3919 userlibandfileserver/fileserver/group/release.txt --- a/userlibandfileserver/fileserver/group/release.txt Fri Apr 23 22:14:19 2010 +0100 +++ b/userlibandfileserver/fileserver/group/release.txt Fri Apr 23 22:20:31 2010 +0100 @@ -1,3 +1,12 @@ +Version 2.00.3031 +================= +(Made by vfebvre 15/04/2010) + +1. migubarr + 1. REQ 415-7212 NFE drive encryption on Demand Paging-enabled device, kernelhwsrv/MCL + PackageReleaseID=453228 FeatureReleaseID=447937 + + Version 2.00.3030 ================= (Made by vfebvre 14/04/2010) diff -r 70ba09fd07a5 -r fc55edbf3919 userlibandfileserver/fileserver/inc/f32ver.h --- a/userlibandfileserver/fileserver/inc/f32ver.h Fri Apr 23 22:14:19 2010 +0100 +++ b/userlibandfileserver/fileserver/inc/f32ver.h Fri Apr 23 22:20:31 2010 +0100 @@ -58,6 +58,6 @@ @see TVersion */ -const TInt KF32BuildVersionNumber=3030; +const TInt KF32BuildVersionNumber=3031; // #endif diff -r 70ba09fd07a5 -r fc55edbf3919 userlibandfileserver/fileserver/sfile/sf_drv.cpp --- a/userlibandfileserver/fileserver/sfile/sf_drv.cpp Fri Apr 23 22:14:19 2010 +0100 +++ b/userlibandfileserver/fileserver/sfile/sf_drv.cpp Fri Apr 23 22:20:31 2010 +0100 @@ -233,7 +233,7 @@ if (iReason==KErrNone && CurrentMount().LockStatus() > 0) { - //-- this meand that the mount has drive access objetcs opened (RFormat or RRawDisk) + //-- this means that the mount has drive access objects opened (RFormat or RRawDisk) __PRINT1(_L("TDrive::CheckMount() Mount is locked! LockStaus:%d"), CurrentMount().LockStatus()); return KErrInUse; } @@ -547,6 +547,19 @@ TRAP(r,CurrentMount().FinaliseMountL(aOperation, aParam1, aParam2)); TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFinaliseMount2Ret, EF32TraceUidFileSys, r); + // Pass FinaliseDrive notification down to media driver + TInt driveNumber = DriveNumber(); + if (LocalDrives::IsValidDriveMapping(driveNumber) && !LocalDrives::IsProxyDrive(driveNumber)) + { + TBusLocalDrive& drv = LocalDrives::GetLocalDrive(driveNumber); + + TLocalDriveFinaliseInfoBuf finaliseBuf; + finaliseBuf().iMode = aOperation; + + // notify local drive, ignore the error + drv.QueryDevice(RLocalDrive::EQueryFinaliseDrive, finaliseBuf); + } + return r; } @@ -815,7 +828,7 @@ // Check that the sharing rules are obeyed. // { - + // Check the correct share modes are passed in switch (aReqShare) { case EFileShareExclusive: @@ -824,47 +837,46 @@ case EFileShareReadersOrWriters: break; default: - return(KErrArgument); + return KErrArgument; } + + // Check the share mode of the file switch (aFile.iShare) { case EFileShareExclusive: - return(KErrInUse); + return KErrInUse; case EFileShareReadersOnly: case EFileShareAny: if (aReqShare != aFile.iShare && aReqShare != EFileShareReadersOrWriters) - return(KErrInUse); + { + return KErrInUse; + } break; case EFileShareReadersOrWriters: - if (aReqShare==EFileShareExclusive) - return(KErrInUse); + if (aReqShare == EFileShareExclusive) + { + return KErrInUse; + } // - // If the file is currently open as EFileShareReadersOrWriters then + // If the file is currently opened as EFileShareReadersOrWriters then // promote the share to the requested share mode. + // + // If the requested share is EFileShareReadersOnly, verify that no + // other share has the file opened for writing. // - // If the requested share is EFileShareReadersOnly, verfiy that no - // other share has the file open for writing. - // - if (aReqShare == EFileShareReadersOnly) { - FileShares->Lock(); - TInt count = FileShares->Count(); - while(count--) + TDblQueIter fileShareIter(aFile.FileShareList()); + CFileShare* pFileShare; + while ((pFileShare = fileShareIter++) != NULL) { - CFileShare* share = (CFileShare*)(*FileShares)[count]; - if (&share->File() == &aFile) + if(pFileShare->iMode & EFileWrite) { - if(share->iMode & EFileWrite) - { - FileShares->Unlock(); - return KErrInUse; - } + return KErrInUse; } } - FileShares->Unlock(); } break; @@ -872,7 +884,8 @@ Fault(EDrvIllegalShareValue); break; } - return(KErrNone); + + return KErrNone; } void TDrive::DriveInfo(TDriveInfo& anInfo) @@ -1332,88 +1345,90 @@ if ((aMode & EDeleteOnClose) && (anOpen!=EFileCreate)) User::Leave(KErrArgument); - CFileCB* pF=LocateFile(aName); + CFileCB* pFile=LocateFile(aName); CFileCache* pFileCache = NULL; - TBool openFile=EFalse; - if (pF!=NULL) + TBool openFile=EFalse; // True if file is being opened for the first time + if (pFile!=NULL) // File is already opened on the drive { - if (pF->iShare==EFileShareReadersOnly && (aMode&EFileWrite)!=0) + if (pFile->iShare==EFileShareReadersOnly && (aMode&EFileWrite)) User::Leave(KErrInUse); if (anOpen==EFileCreate) User::Leave(KErrAlreadyExists); - TInt r=ValidateShare(*pF,share); + TInt r=ValidateShare(*pFile,share); if (r!=KErrNone) User::Leave(r); - if ((r=pF->Open())!=KErrNone) + if ((r=pFile->Open())!=KErrNone) User::Leave(r); - aFileCB=pF; - pFileCache = pF->FileCache(); + + aFileCB=pFile; + pFileCache = pFile->FileCache(); } else { TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileL, EF32TraceUidFileSys, &FSys(), DriveNumber()); //-- construct CFileCB object, belonging to the corresponding mount - pF = aFileCB = CurrentMount().NewFileL(); - - TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileLRet, EF32TraceUidFileSys, r, pF); + pFile = aFileCB = CurrentMount().NewFileL(); + + TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileSystemNewFileLRet, EF32TraceUidFileSys, r, pFile); TDrive* createdDrive=!aRequest->SubstedDrive() ? this : aRequest->SubstedDrive(); HBufC* fileName = CreateFileNameL(aName); - pF->InitL(this, createdDrive, fileName); - - - pF->iShare = share; + pFile->InitL(this, createdDrive, fileName); + + pFile->iShare = share; + pFile->SetSequentialMode(aMode & EFileSequential); openFile=ETrue; - CurrentMount().iMountQ.AddLast(*pF); - Files->AddL(pF,ETrue); + CurrentMount().iMountQ.AddLast(*pFile); + Files->AddL(pFile,ETrue); + __PRINT1(_L("TDrive::FileOpenL - CFileCB->IsSequentialMode = %d"), pFile->IsSequentialMode()); } - CFileShare* pS=aFileShare=new(ELeave) CFileShare(pF); + CFileShare* pFileShare=aFileShare=new(ELeave) CFileShare(pFile); // We need to call CFileCB::PromoteShare immediately after the CFileShare // instance is created since the destructor calls CFileCB::DemoteShare() // which checks the share count is non-zero - pS->iMode=aMode; - pF->PromoteShare(pS); - - pS->InitL(); + pFileShare->iMode=aMode; + pFile->PromoteShare(pFileShare); + + pFileShare->InitL(); aFileCB=NULL; - FileShares->AddL(pS,ETrue); - aHandle=aRequest->Session()->Handles().AddL(pS,ETrue); + FileShares->AddL(pFileShare,ETrue); + aHandle=aRequest->Session()->Handles().AddL(pFileShare,ETrue); if (openFile) { - TRACEMULT5(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenL, EF32TraceUidFileSys, DriveNumber(), aName, aMode, (TUint) anOpen, (TUint) pF); - CurrentMount().FileOpenL(aName,aMode,anOpen,pF); + TRACEMULT5(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenL, EF32TraceUidFileSys, DriveNumber(), aName, aMode, (TUint) anOpen, (TUint) pFile); + CurrentMount().FileOpenL(aName,aMode,anOpen,pFile); TRACE1(UTF::EBorder, UTraceModuleFileSys::ECMountCBFileOpenLRet, EF32TraceUidFileSys, KErrNone); // Delete on close may now be safely flagged if required. // The file did not exist on the media prior to the // CMountCB::FileOpenL() call for the case of a create. if ((aMode & EDeleteOnClose) && (anOpen==EFileCreate)) - pF->SetDeleteOnClose(); - - TBool localBufferSuppport = (CurrentMount().LocalBufferSupport(pF) == KErrNone)?(TBool)ETrue:(TBool)EFalse; - pF->SetLocalBufferSupport(localBufferSuppport); + pFile->SetDeleteOnClose(); + + TBool localBufferSuppport = (CurrentMount().LocalBufferSupport(pFile) == KErrNone)?(TBool)ETrue:(TBool)EFalse; + pFile->SetLocalBufferSupport(localBufferSuppport); if (localBufferSuppport) { - // if file exists on closed queue resurrect it or discard it, + // If file exists on closed queue resurrect it or discard it, // depending on the file open mode pFileCache = LocateClosedFile(aName, anOpen == EFileOpen?(TBool)ETrue:(TBool)EFalse); if (pFileCache) { - pFileCache = pFileCache->ReNewL(*pS); // NB may return NULL if caching not enabled + pFileCache = pFileCache->ReNewL(*pFileShare); // NB may return NULL if caching not enabled } else { - pFileCache = CFileCache::NewL(*pS); // NB may return NULL if caching not enabled + pFileCache = CFileCache::NewL(*pFileShare); // NB may return NULL if caching not enabled } if (pFileCache) - // set the cached size to be the same as the uncached size - pF->SetCachedSize64(pF->Size64()); + // Set the cached size to be the same as the uncached size + pFile->SetCachedSize64(pFile->Size64()); } else { @@ -1421,9 +1436,9 @@ } } - // initialize share mode flags + // Initialize share mode flags if (pFileCache != NULL) - pFileCache->Init(*pS); + pFileCache->Init(*pFileShare); } TInt TDrive::FileOpen(CFsRequest* aRequest,TInt& aHandle,const TDesC& aName,TUint aMode,TFileOpen anOpen) @@ -1435,7 +1450,7 @@ CFileCB* pF=NULL; CFileShare* pS=NULL; aHandle=0; - TRAPD(r,FileOpenL(aRequest,aHandle,aName,aMode,anOpen,pF,pS)) + TRAPD(r,FileOpenL(aRequest,aHandle,aName,aMode,anOpen,pF,pS)); // Allow files > 2GB-1 to be opened only if EFileBigFile is specified in iMode if (r == KErrNone && pS && ((TUint64)pS->File().Size64() > KMaxLegacyFileSize) && (!(pS->IsFileModeBig())))