# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1266617451 -7200 # Node ID 4a8fed1c0ef66e39242bfce74babbe3ca64e841e # Parent 2d65c2f76d7b90fe00d7056c4c1a20714bc112c8 Revision: 201007 Kit: 201007 diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 bsptemplate/asspandvariant/template_variant/bld.inf --- a/bsptemplate/asspandvariant/template_variant/bld.inf Tue Feb 02 01:24:03 2010 +0200 +++ b/bsptemplate/asspandvariant/template_variant/bld.inf Sat Feb 20 00:10:51 2010 +0200 @@ -108,12 +108,35 @@ // PRJ_EXTENSIONS -start extension base/bootstrap + +#ifdef SBSV2 // If using SBSv2 with bootstrap FLM, MEMMODEL MUST begin with a capital letter + +start extension base.bootstrap bootstrap #ifdef SYMBIAN_OLD_EXPORT_LOCATION -option INC_PATH /epoc32/include +option INC_PATH $(EPOCROOT)epoc32/include #else -option INC_PATH /epoc32/include/platform +option INC_PATH $(EPOCROOT)epoc32/include/platform +#endif + +option NAME _template_bootrom +option CPU arm +option MEMMODEL Multiple +option SOURCES ./bootstrap/template.s +option EXTRA_SRC_PATH ./bootstrap +option INCLUDES ./config.inc +option E32PATH ../../../kernel/eka/../. + +end + +#else // !SBSV2 + +start extension base/bootstrap bootstrap + +#ifdef SYMBIAN_OLD_EXPORT_LOCATION +option INC_PATH $(EPOCROOT)epoc32/include +#else +option INC_PATH $(EPOCROOT)epoc32/include/platform #endif option NAME _template_bootrom @@ -126,3 +149,4 @@ end +#endif // !SBSV2 diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 bsptemplate/asspandvariant/template_variant/specific/keyboard_interrupt.cpp --- a/bsptemplate/asspandvariant/template_variant/specific/keyboard_interrupt.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/bsptemplate/asspandvariant/template_variant/specific/keyboard_interrupt.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -182,6 +182,10 @@ { DKeyboardTemplate& k=*(DKeyboardTemplate*)aPtr; Interrupt::Disable(KIntIdKeyboard); + + // Add the timing of key interrupts as entropy data for the RNG + Interrupt::AddTimingEntropy(); + k.iEventDfc.Add(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 bsptemplate/asspandvariant/template_variant/specific/xyin.cpp --- a/bsptemplate/asspandvariant/template_variant/specific/xyin.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/bsptemplate/asspandvariant/template_variant/specific/xyin.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -599,6 +599,9 @@ Interrupt::Disable(KIntIdDigitiser); // do NOT disable the capability to generate interrupts at the source + // Add the timing of pen interrupts as entropy data for the RNG + Interrupt::AddTimingEntropy(); + if (KPenDownDelayTime>0) // need to check this config param as it might be zero! iTimerInt.OneShot(KPenDownDelayTime); // start a debounce timer which will queue a DFC to process the interrupt else diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/base_e32.mrp --- a/kernel/eka/base_e32.mrp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/base_e32.mrp Sat Feb 20 00:10:51 2010 +0200 @@ -32,15 +32,15 @@ binary \sf\os\kernelhwsrv\kernel\eka all exports \sf\os\kernelhwsrv\kernel\eka --export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec.zip \epoc32\include\exec_enum.h --export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec.zip \epoc32\include\exec_user.h --export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec.zip \epoc32\include\kernel\exec_kernel.h +-export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec_hr.zip \epoc32\include\platform\exec_enum.h +-export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec_hr.zip \epoc32\include\platform\exec_user.h +-export_file \sf\os\kernelhwsrv\kernel\eka\include\dummy_genexec_hr.zip \epoc32\include\platform\kernel\exec_kernel.h notes_source \component_defs\release.src -binary \epoc32\include\exec_enum.h -binary \epoc32\include\exec_user.h -binary \epoc32\include\kernel\exec_kernel.h +binary \epoc32\include\platform\exec_enum.h +binary \epoc32\include\platform\exec_user.h +binary \epoc32\include\platform\kernel\exec_kernel.h ipr D ipr D \sf\os\kernelhwsrv\kernel\eka\include\memmodel\epoc\multiple\arm diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bmarm/econs.def --- a/kernel/eka/bmarm/econs.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bmarm/econs.def Sat Feb 20 00:10:51 2010 +0200 @@ -31,4 +31,5 @@ Type__C11TConsoleKey @ 30 NONAME ; TConsoleKey::Type(void) const Version__8RConsole @ 31 NONAME ; RConsole::Version(void) ClearScreen__8RConsole @ 32 NONAME ; RConsole::ClearScreen(void) + PointerNumber__C11TConsoleKey @ 33 NONAME ; TConsoleKey::PointerNumber(void) const diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bmarm/ekernsmp.def --- a/kernel/eka/bmarm/ekernsmp.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bmarm/ekernsmp.def Sat Feb 20 00:10:51 2010 +0200 @@ -1041,4 +1041,9 @@ DestroyKernelMapObject__4KernRP16TKernelMapObject @ 1040 NONAME R3UNUSED ; Kern::DestroyKernelMapObject(TKernelMapObject *&) MapAndPinMemory__4KernP16TKernelMapObjectP7DThreadUlUiUiRUlPUl @ 1041 NONAME ; Kern::MapAndPinMemory(TKernelMapObject *, DThread *, unsigned long, unsigned int, unsigned int, unsigned long &, unsigned long *) UnmapAndUnpinMemory__4KernP16TKernelMapObject @ 1042 NONAME R3UNUSED ; Kern::UnmapAndUnpinMemory(TKernelMapObject *) + AddTimingEntropy__9Interrupt @ 1043 NONAME R3UNUSED ; Interrupt::AddTimingEntropy(void) + RandomSalt__4KernUlUi @ 1044 NONAME R3UNUSED ; Kern::RandomSalt(unsigned long, unsigned int) + RandomSalt__4KernUxUi @ 1045 NONAME ; Kern::RandomSalt(unsigned long long, unsigned int) + RandomSalt__4KernPCUcUiUi @ 1046 NONAME R3UNUSED ; Kern::RandomSalt(unsigned char const *, unsigned int, unsigned int) + SecureRandom__4KernR5TDes8 @ 1047 NONAME R3UNUSED ; Kern::SecureRandom(TDes8 &) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bmarm/ekernu.def --- a/kernel/eka/bmarm/ekernu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bmarm/ekernu.def Sat Feb 20 00:10:51 2010 +0200 @@ -1037,4 +1037,9 @@ DestroyKernelMapObject__4KernRP16TKernelMapObject @ 1036 NONAME R3UNUSED ; Kern::DestroyKernelMapObject(TKernelMapObject *&) MapAndPinMemory__4KernP16TKernelMapObjectP7DThreadUlUiUiRUlPUl @ 1037 NONAME ; Kern::MapAndPinMemory(TKernelMapObject *, DThread *, unsigned long, unsigned int, unsigned int, unsigned long &, unsigned long *) UnmapAndUnpinMemory__4KernP16TKernelMapObject @ 1038 NONAME R3UNUSED ; Kern::UnmapAndUnpinMemory(TKernelMapObject *) + AddTimingEntropy__9Interrupt @ 1039 NONAME R3UNUSED ; Interrupt::AddTimingEntropy(void) + RandomSalt__4KernUlUi @ 1040 NONAME R3UNUSED ; Kern::RandomSalt(unsigned long, unsigned int) + RandomSalt__4KernUxUi @ 1041 NONAME ; Kern::RandomSalt(unsigned long long, unsigned int) + RandomSalt__4KernPCUcUiUi @ 1042 NONAME R3UNUSED ; Kern::RandomSalt(unsigned char const *, unsigned int, unsigned int) + SecureRandom__4KernR5TDes8 @ 1043 NONAME R3UNUSED ; Kern::SecureRandom(TDes8 &) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bmarm/euseru.def --- a/kernel/eka/bmarm/euseru.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bmarm/euseru.def Sat Feb 20 00:10:51 2010 +0200 @@ -2231,4 +2231,8 @@ LoadLocale__15TExtendedLocaleRC7TDesC16N21 @ 2230 NONAME ; TExtendedLocale::LoadLocale(TDesC16 const &, TDesC16 const &, TDesC16 const &) RegionCode__4User @ 2231 NONAME R3UNUSED ; User::RegionCode(void) SetReadOnly__16TChunkCreateInfo @ 2232 NONAME R3UNUSED ; TChunkCreateInfo::SetReadOnly(void) + RandomL__4MathR5TDes8 @ 2233 NONAME R3UNUSED ; Math::RandomL(TDes8 &) + RandomL__4Math @ 2234 NONAME R3UNUSED ; Math::RandomL(void) + Random__4MathR5TDes8 @ 2235 NONAME R3UNUSED ; Math::Random(TDes8 &) + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bwins/econs.def --- a/kernel/eka/bwins/econs.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bwins/econs.def Sat Feb 20 00:10:51 2010 +0200 @@ -31,4 +31,5 @@ ?Type@TConsoleKey@@QBEHXZ @ 30 NONAME ; public: int __thiscall TConsoleKey::Type(void)const ?Version@RConsole@@QAE?AVTVersion@@XZ @ 31 NONAME ; public: class TVersion __thiscall RConsole::Version(void) ?Write@RConsole@@QAEHABVTDesC16@@@Z @ 32 NONAME ; public: int __thiscall RConsole::Write(class TDesC16 const &) + ?PointerNumber@TConsoleKey@@QBEEXZ @ 33 NONAME ; public: unsigned char __thiscall TConsoleKey::PointerNumber(void)const diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bwins/ekernu.def --- a/kernel/eka/bwins/ekernu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bwins/ekernu.def Sat Feb 20 00:10:51 2010 +0200 @@ -925,4 +925,8 @@ ?MapAndPinMemory@Kern@@SAHPAVTKernelMapObject@@PAVDThread@@KIIAAKPAK@Z @ 924 NONAME ; int Kern::MapAndPinMemory(class TKernelMapObject *, class DThread *, unsigned long, unsigned int, unsigned int, unsigned long &, unsigned long *) ?CreateKernelMapObject@Kern@@SAHAAPAVTKernelMapObject@@I@Z @ 925 NONAME ; int Kern::CreateKernelMapObject(class TKernelMapObject * &, unsigned int) ?DestroyKernelMapObject@Kern@@SAXAAPAVTKernelMapObject@@@Z @ 926 NONAME ; void Kern::DestroyKernelMapObject(class TKernelMapObject * &) + ?RandomSalt@Kern@@SAXKI@Z @ 927 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned long,unsigned int) + ?RandomSalt@Kern@@SAX_KI@Z @ 928 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned __int64,unsigned int) + ?RandomSalt@Kern@@SAXPBEII@Z @ 929 NONAME ; void Kern::RandomSalt(unsigned char const *, unsigned int, unsigned int) + ?SecureRandom@Kern@@SAHAAVTDes8@@@Z @ 930 NONAME ; int Kern::SecureRandom(class TDes8 &) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bwins/euseru.def --- a/kernel/eka/bwins/euseru.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bwins/euseru.def Sat Feb 20 00:10:51 2010 +0200 @@ -2179,4 +2179,8 @@ ?LoadLocaleAspect@TExtendedLocale@@QAEHABVTDesC16@@@Z @ 2178 NONAME ; int TExtendedLocale::LoadLocaleAspect(class TDesC16 const &) ?RegionCode@User@@SA?AW4TRegionCode@@XZ @ 2179 NONAME ; enum TRegionCode User::RegionCode(void) ?SetReadOnly@TChunkCreateInfo@@QAEXXZ @ 2180 NONAME ; public: void __thiscall TChunkCreateInfo::SetReadOnly(void) + ?RandomL@Math@@SAXAAVTDes8@@@Z @ 2181 NONAME ; void Math::RandomL(class TDes8 &) + ?Random@Math@@SAXAAVTDes8@@@Z @ 2182 NONAME ; void Math::Random(class TDes8 &) + ?RandomL@Math@@SAKXZ @ 2183 NONAME ; unsigned long Math::RandomL(void) + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86/econs.def --- a/kernel/eka/bx86/econs.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86/econs.def Sat Feb 20 00:10:51 2010 +0200 @@ -31,4 +31,5 @@ ?Type@TConsoleKey@@QBEHXZ @ 30 NONAME ; public: int __thiscall TConsoleKey::Type(void)const ?Version@RConsole@@QAE?AVTVersion@@XZ @ 31 NONAME ; public: class TVersion __thiscall RConsole::Version(void) ?Write@RConsole@@QAEHABVTDesC16@@@Z @ 32 NONAME ; public: int __thiscall RConsole::Write(class TDesC16 const &) + ?PointerNumber@TConsoleKey@@QBEEXZ @ 33 NONAME ; public: unsigned char __thiscall TConsoleKey::PointerNumber(void)const diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86/ekernsmp.def --- a/kernel/eka/bx86/ekernsmp.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86/ekernsmp.def Sat Feb 20 00:10:51 2010 +0200 @@ -999,4 +999,9 @@ ?DestroyKernelMapObject@Kern@@SAXAAPAVTKernelMapObject@@@Z @ 998 NONAME ; public: static void __cdecl Kern::DestroyKernelMapObject(class TKernelMapObject * &) ?MapAndPinMemory@Kern@@SAHPAVTKernelMapObject@@PAVDThread@@KIIAAKPAK@Z @ 999 NONAME ; public: static int __cdecl Kern::MapAndPinMemory(class TKernelMapObject *,class DThread *,unsigned long,unsigned int,unsigned int,unsigned long &,unsigned long *) ?UnmapAndUnpinMemory@Kern@@SAXPAVTKernelMapObject@@@Z @ 1000 NONAME ; public: static void __cdecl Kern::UnmapAndUnpinMemory(class TKernelMapObject *) + ?AddTimingEntropy@Interrupt@@SAXXZ @ 1001 NONAME ; public: static void __cdecl Interrupt::AddTimingEntropy(void) + ?RandomSalt@Kern@@SAXKI@Z @ 1002 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned long,unsigned int) + ?RandomSalt@Kern@@SAX_KI@Z @ 1003 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned __int64,unsigned int) + ?RandomSalt@Kern@@SAXPBEII@Z @ 1004 NONAME ; void Kern::RandomSalt(unsigned char const *, unsigned int, unsigned int) + ?SecureRandom@Kern@@SAHAAVTDes8@@@Z @ 1005 NONAME ; int Kern::SecureRandom(class TDes8 &) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86/ekernu.def --- a/kernel/eka/bx86/ekernu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86/ekernu.def Sat Feb 20 00:10:51 2010 +0200 @@ -943,4 +943,9 @@ ?DestroyKernelMapObject@Kern@@SAXAAPAVTKernelMapObject@@@Z @ 942 NONAME ; public: static void __cdecl Kern::DestroyKernelMapObject(class TKernelMapObject * &) ?MapAndPinMemory@Kern@@SAHPAVTKernelMapObject@@PAVDThread@@KIIAAKPAK@Z @ 943 NONAME ; public: static int __cdecl Kern::MapAndPinMemory(class TKernelMapObject *,class DThread *,unsigned long,unsigned int,unsigned int,unsigned long &,unsigned long *) ?UnmapAndUnpinMemory@Kern@@SAXPAVTKernelMapObject@@@Z @ 944 NONAME ; public: static void __cdecl Kern::UnmapAndUnpinMemory(class TKernelMapObject *) + ?AddTimingEntropy@Interrupt@@SAXXZ @ 945 NONAME ; public: static void __cdecl Interrupt::AddTimingEntropy(void) + ?RandomSalt@Kern@@SAXKI@Z @ 946 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned long,unsigned int) + ?RandomSalt@Kern@@SAX_KI@Z @ 947 NONAME ; public: static void __cdecl Kern::RandomSalt(unsigned __int64,unsigned int) + ?RandomSalt@Kern@@SAXPBEII@Z @ 948 NONAME ; void Kern::RandomSalt(unsigned char const *, unsigned int, unsigned int) + ?SecureRandom@Kern@@SAHAAVTDes8@@@Z @ 949 NONAME ; int Kern::SecureRandom(class TDes8 &) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86/euseru.def --- a/kernel/eka/bx86/euseru.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86/euseru.def Sat Feb 20 00:10:51 2010 +0200 @@ -2179,4 +2179,8 @@ ?LoadLocaleAspect@TExtendedLocale@@QAEHABVTDesC16@@@Z @ 2178 NONAME ; int TExtendedLocale::LoadLocaleAspect(class TDesC16 const &) ?RegionCode@User@@SA?AW4TRegionCode@@XZ @ 2179 NONAME ; enum TRegionCode User::RegionCode(void) ?SetReadOnly@TChunkCreateInfo@@QAEXXZ @ 2180 NONAME ; public: void __thiscall TChunkCreateInfo::SetReadOnly(void) + ?RandomL@Math@@SAXAAVTDes8@@@Z @ 2181 NONAME ; void Math::RandomL(class TDes8 &) + ?Random@Math@@SAXAAVTDes8@@@Z @ 2182 NONAME ; void Math::Random(class TDes8 &) + ?RandomL@Math@@SAKXZ @ 2183 NONAME ; unsigned long Math::RandomL(void) + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86gcc/ekernsmp.def --- a/kernel/eka/bx86gcc/ekernsmp.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86gcc/ekernsmp.def Sat Feb 20 00:10:51 2010 +0200 @@ -1087,4 +1087,9 @@ _ZN4Kern19UnmapAndUnpinMemoryEP16TKernelMapObject @ 1086 NONAME _ZN4Kern21CreateKernelMapObjectERP16TKernelMapObjectj @ 1087 NONAME _ZN4Kern22DestroyKernelMapObjectERP16TKernelMapObject @ 1088 NONAME + _ZN9Interrupt16AddTimingEntropyEv @ 1089 NONAME + _ZN4Kern10RandomSaltEmj @ 1090 NONAME + _ZN4Kern10RandomSaltEyj @ 1091 NONAME + _ZN4Kern10RandomSaltEPKhjj @ 1092 NONAME + _ZN4Kern12SecureRandomER5TDes8 @ 1093 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86gcc/ekernu.def --- a/kernel/eka/bx86gcc/ekernu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86gcc/ekernu.def Sat Feb 20 00:10:51 2010 +0200 @@ -1026,4 +1026,9 @@ _ZN4Kern19UnmapAndUnpinMemoryEP16TKernelMapObject @ 1025 NONAME _ZN4Kern21CreateKernelMapObjectERP16TKernelMapObjectj @ 1026 NONAME _ZN4Kern22DestroyKernelMapObjectERP16TKernelMapObject @ 1027 NONAME + _ZN9Interrupt16AddTimingEntropyEv @ 1028 NONAME + _ZN4Kern10RandomSaltEmj @ 1029 NONAME + _ZN4Kern10RandomSaltEyj @ 1030 NONAME + _ZN4Kern10RandomSaltEPKhjj @ 1031 NONAME + _ZN4Kern12SecureRandomER5TDes8 @ 1032 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/bx86gcc/euseru.def --- a/kernel/eka/bx86gcc/euseru.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/bx86gcc/euseru.def Sat Feb 20 00:10:51 2010 +0200 @@ -2458,3 +2458,6 @@ _ZN15TExtendedLocale10LoadLocaleERK7TDesC16S2_S2_ @ 2457 NONAME _ZN15TExtendedLocale16LoadLocaleAspectERK7TDesC16 @ 2458 NONAME _ZN16TChunkCreateInfo11SetReadOnlyEv @ 2459 NONAME + _ZN4Math7RandomLER5TDes8 @ 2460 NONAME + _ZN4Math6RandomER5TDes8 @ 2461 NONAME + _ZN4Math7RandomLEv @ 2462 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/bld.inf --- a/kernel/eka/compsupp/bld.inf Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/compsupp/bld.inf Sat Feb 20 00:10:51 2010 +0200 @@ -29,20 +29,6 @@ compsupp.iby /epoc32/rom/include/ -// Unzip runtimes not being built - -#if !defined(ARMCC_2_2) -:zip rt_2_2_export.zip -#endif - -#if !defined(ARMCC_3_1) -:zip rt_3_1_export.zip -#endif - -#if !defined(ARMCC_4_0) -:zip rt_4_0_export.zip -#endif - PRJ_MMPFILES @@ -71,5 +57,22 @@ #endif +PRJ_EXTENSIONS + +// Unzip RVCT3.1 runtime if being built with RVCT2.2 or RVCT4.0 + +start extension tools/compsupp + +#if defined(ARMCC_2_2) || defined(ARMCC_4_0) +option FILE $(EXTENSION_ROOT)/rt_3_1.zip +#elif defined(ARMCC_3_1) +option FILE $(EXTENSION_ROOT)/rt_2_2.zip #endif +option TODIR $(EPOCROOT)epoc32/release + +end + +#endif // #if !defined GCCXML && !defined GCCE + + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/rt_2_2.zip Binary file kernel/eka/compsupp/rt_2_2.zip has changed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/rt_2_2_export.zip Binary file kernel/eka/compsupp/rt_2_2_export.zip has changed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/rt_3_1.zip Binary file kernel/eka/compsupp/rt_3_1.zip has changed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/rt_3_1_export.zip Binary file kernel/eka/compsupp/rt_3_1_export.zip has changed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/compsupp/rt_4_0_export.zip Binary file kernel/eka/compsupp/rt_4_0_export.zip has changed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/locmedia/locmedia.cpp --- a/kernel/eka/drivers/locmedia/locmedia.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/locmedia/locmedia.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -4947,8 +4947,10 @@ if (r != KErrNone) { - OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< retval=%d",r); - return r; + OstTrace1(TRACE_FLOW, LOCRV_REGISTERPAGINGDEVICE_EXIT9, "< Caps::retval=%d - return KErrNotSupported",r); + // Media driver failure; media maybe recoverable after boot. + // Can't register any page drives so return not supported. + return KErrNotSupported; } TLocDrv* drive; @@ -5012,7 +5014,7 @@ Kern::Printf("iRomPagingDriveNumber 0x%x\n", pagingDevice->iRomPagingDriveNumber); Kern::Printf("iDataPagingDriveNumber 0x%x\n", pagingDevice->iDataPagingDriveNumber); Kern::Printf("iSwapSize 0x%x\n", pagingDevice->iSwapSize); - #endif +#endif // This table is indexed by DPagingDevice::TType diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/medmmc/bgahsmmcptn.cpp --- a/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -119,7 +119,7 @@ } else if ( PartitionIsFAT(aDrive.iPartitionType) || PartitionIsFAT32(aDrive.iPartitionType) ) { - Info().iDriveAtt = iPartitionAttributes[aDrive.iPartitionNumber]; + Info().iDriveAtt |= iPartitionAttributes[aDrive.iPartitionNumber]; } return KErrNone; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def --- a/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def Sat Feb 20 00:10:51 2010 +0200 @@ -135,7 +135,7 @@ _ZN8DSDStack6Dummy1Ev @ 134 NONAME _ZN8DSDStack6Dummy2Ev @ 135 NONAME _ZN8DSDStack6Dummy3Ev @ 136 NONAME - _ZN8DSDStack6Dummy4Ev @ 137 NONAME + _ZN8DSDStack8CardTypeEii @ 137 NONAME _ZNK8DSDStack12AllocSessionERK12TMMCCallBack @ 138 NONAME _ZTI12TSDCardArray @ 139 NONAME ; ## _ZTI7TSDCard @ 140 NONAME ; ## diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp --- a/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -16,7 +16,7 @@ #include #include "OstTraceDefinitions.h" #ifdef OST_TRACE_COMPILER_IN_USE -#include "locmedia_ost.h" +#include "../../../../include/drivers/locmedia_ost.h" #ifdef __VC32__ #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" #endif @@ -594,8 +594,16 @@ SMF_BEGIN - OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM1, "EStBegin" ); - iCxCardType = ESDCardTypeUnknown; + OstTrace0( TRACE_INTERNALS, DSDSTACK_INITIALISEMEMORYCARDSM1, "EStBegin" ); + + iCxCardType = CardType(MMCSocket()->iSocketNumber, iCxCardCount); + + if (iCxCardType==ESDCardTypeIsMMC) + { + // Skip the SD Protocol Seq. + SMF_INVOKES(GoIdleSMST, EStCheckVoltage); + } + s.iCardP = NULL; // This stops ExecCommandSM() from setting old RCA when sending CMD55 // Send CMD0 to initialise memory @@ -1623,7 +1631,22 @@ return new DSDSession(aCallBack); } +EXPORT_C DSDStack::TSDCardType DSDStack::CardType(TInt /*aSocket*/, TInt /*aCardNumber*/) +/** + * This method allows a preset card type to be specified for a given slot/socket. + * The SD protocol stack attempts to identify card types (SD or MMC) through protocol responses; + * For embedded media (eMMC or eSD) this is unnecessary as the media type is already known and cannot change. + * Licensee may override this function to specify the preset card type. + * @param aSocket Socket to be queried for card type. + * @param aCardNumber Card number attached to Socket to be queried for card type. + * @return Preset card type + */ + { + // Default implmentation. + return DSDStack::ESDCardTypeUnknown; + } + + EXPORT_C void DSDStack::Dummy1() {} EXPORT_C void DSDStack::Dummy2() {} EXPORT_C void DSDStack::Dummy3() {} -EXPORT_C void DSDStack::Dummy4() {} diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdio/sdiostack.cpp --- a/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdio/sdiostack.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdio/sdiostack.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -165,6 +165,14 @@ { SMF_GOTOS(EStCheckNextCard) } + + iCxCardType = CardType(MMCSocket()->iSocketNumber, iCxCardCount); + + if (iCxCardType!=ESDCardTypeUnknown) + { + // Skip the SDIO Protocol Seq. + SMF_GOTOS(EStInitMemoryCard); + } TRACE2(TTraceContext(EBorder), UTraceModuleEPBusSDIO::ESDIODSDIOStackPSLCalledAddressCard, reinterpret_cast(this), iCxCardCount); // @SymTraceDataPublishedTvk AddressCard(iCxCardCount); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/mmc/session.cpp --- a/kernel/eka/drivers/pbus/mmc/session.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/mmc/session.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -16,7 +16,7 @@ #include #include "OstTraceDefinitions.h" #ifdef OST_TRACE_COMPILER_IN_USE -#include "locmedia_ost.h" +#include "../../../include/drivers/locmedia_ost.h" #ifdef __VC32__ #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/mmc/stack.cpp --- a/kernel/eka/drivers/pbus/mmc/stack.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/mmc/stack.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -22,7 +22,7 @@ #include "OstTraceDefinitions.h" #ifdef OST_TRACE_COMPILER_IN_USE -#include "locmedia_ost.h" +#include "../../../include/drivers/locmedia_ost.h" #ifdef __VC32__ #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/pbusmedia.cpp --- a/kernel/eka/drivers/pbus/pbusmedia.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/pbusmedia.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -18,7 +18,7 @@ #include #include "OstTraceDefinitions.h" #ifdef OST_TRACE_COMPILER_IN_USE -#include "locmedia_ost.h" +#include "../../include/drivers/locmedia_ost.h" #ifdef __VC32__ #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/pbus/spbus.cpp --- a/kernel/eka/drivers/pbus/spbus.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/pbus/spbus.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -18,7 +18,7 @@ #include #include "OstTraceDefinitions.h" #ifdef OST_TRACE_COMPILER_IN_USE -#include "locmedia_ost.h" +#include "../../include/drivers/locmedia_ost.h" #ifdef __VC32__ #pragma warning(disable: 4127) // disabling warning "conditional expression is constant" #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/usbc/d_usbc.cpp --- a/kernel/eka/drivers/usbc/d_usbc.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/usbc/d_usbc.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -153,6 +153,7 @@ __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcChannel::~DLddUsbcChannel()")); if (iController) { + iController->DeRegisterClient(this); iStatusCallbackInfo.Cancel(); iEndpointStatusCallbackInfo.Cancel(); iOtgFeatureCallbackInfo.Cancel(); @@ -164,7 +165,6 @@ iController->ReleaseDeviceControl(this); iOwnsDeviceControl = EFalse; } - iController->DeRegisterClient(this); DestroyEp0(); delete iStatusFifo; Kern::DestroyClientRequest(iStatusChangeReq); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/usbcc/ps_usbc.cpp --- a/kernel/eka/drivers/usbcc/ps_usbc.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/usbcc/ps_usbc.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -672,14 +672,14 @@ #ifdef USB_OTG_CLIENT iClientSupportReady = ETrue; const TInt r = EvaluateOtgConnectFlags(); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); if (iUsbResetDeferred) // implies (iOtgHnpHandledByHw == ETrue) { __KTRACE_OPT(KUSB, Kern::Printf(" Resetting USB Reset 'defer' flag")); iUsbResetDeferred = EFalse; (void) ProcessResetEvent(EFalse); } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); #else const TInt r = UdcConnect(); #endif // USB_OTG_CLIENT @@ -743,9 +743,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: StatusCallback @ 0x%x already registered", &aCallback)); return KErrGeneral; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iStatusCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -761,7 +761,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForStatusChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iStatusCallbacks); TUsbcStatusCallback* p; while ((p = iter++) != NULL) @@ -770,12 +770,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing StatusCallback @ 0x%x", p)); iStatusCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -809,9 +809,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: EpStatusCallback @ 0x%x already registered", &aCallback)); return KErrGeneral; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iEpStatusCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -827,7 +827,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForEndpointStatusChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEpStatusCallbacks); TUsbcEndpointStatusCallback* p; while ((p = iter++) != NULL) @@ -836,12 +836,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing EpStatusCallback @ 0x%x", p)); iEpStatusCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -1056,17 +1056,17 @@ } // Ep0 reads don't need to be prepared - there's always one pending __KTRACE_OPT(KUSB, Kern::Printf(" adding RequestCallback @ 0x%x (ep0)", &aCallback)); - TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iEp0ReadRequestCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); err = KErrNone; if (iEp0_RxExtraData) { __KTRACE_OPT(KUSB, Kern::Printf(" iEp0_RxExtraData: trying again...")); const TBool rx_data = iEp0DataReceiving; - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); err = ProcessEp0ReceiveDone(iEp0_RxExtraCount); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); if (err == KErrNone) { iEp0_RxExtraData = EFalse; @@ -1643,9 +1643,9 @@ __KTRACE_OPT(KUSB, Kern::Printf(" Error: OtgFeatureCallback @ 0x%x already registered", &aCallback)); return KErrAlreadyExists; } - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); iOtgCallbacks.AddLast(aCallback); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } @@ -1661,7 +1661,7 @@ { __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeRegisterForOtgFeatureChange()")); __ASSERT_DEBUG((aClientId != NULL), Kern::Fault(KUsbPILPanicCat, __LINE__)); - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iOtgCallbacks); TUsbcOtgFeatureCallback* p; while ((p = iter++) != NULL) @@ -1670,12 +1670,12 @@ { __KTRACE_OPT(KUSB, Kern::Printf(" removing OtgFeatureCallback @ 0x%x", p)); iOtgCallbacks.Remove(*p); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNone; } } __KTRACE_OPT(KUSB, Kern::Printf(" client not found")); - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return KErrNotFound; } @@ -2881,6 +2881,7 @@ iOtgCallbacks(_FOFF(TUsbcOtgFeatureCallback, iLink)), iReconnectTimer(ReconnectTimerCallback, this), iCableStatusTimer(CableStatusTimerCallback, this), + iUsbLock(TSpinLock::EOrderGenericIrqLow3), iPowerUpDfc(PowerUpDfc, this, 3), iPowerDownDfc(PowerDownDfc, this, 3), iStandby(EFalse), @@ -3765,7 +3766,7 @@ // Ep0 OUT if (aEndpointNum == 0) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEp0ReadRequestCallbacks); TUsbcRequestCallback* p; while ((p = iter++) != NULL) @@ -3778,7 +3779,7 @@ iEp0ReadRequestCallbacks.Remove(*p); } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return; } // Other endpoints @@ -3798,7 +3799,7 @@ // aClientId being NULL means: delete all requests for *all* clients. __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DeleteRequestCallbacks()")); // Ep0 OUT - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEp0ReadRequestCallbacks); TUsbcRequestCallback* p; while ((p = iter++) != NULL) @@ -3809,7 +3810,7 @@ iEp0ReadRequestCallbacks.Remove(*p); } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); // Other endpoints for (TInt i = 1; i < KUsbcEpArraySize; i++) { @@ -4278,7 +4279,23 @@ // notification in any case, even if no cable and/or host are // connected. The next Reset will get us out of it again. iDeviceStateB4Suspend = iDeviceState; - NextDeviceState(EUsbcDeviceStateSuspended); + // Please pay attention to that the above comment now is not accurate! + // It's not updated according the below modification just for keeping the original comment! + // + // Moving to Suspend state arbitrarily will cause DEFECT EDHO-7Y3AAD. + // DEFECT EDHO-7Y3AAD: Connected to the USB Charger, the UI displayed wrongly connected as default mode + // since the iDeviceState changed wrongly from Undefined to Suspended, and keep + // always Suspended becauseof NO Reset coming next! + // So, to fix this defect, the state change notification is modified to be triggerred by loop the current state again + // if the current state is Undefined! + if (EUsbcDeviceStateUndefined != iDeviceState) + { + NextDeviceState(EUsbcDeviceStateSuspended); + } + else + { + NextDeviceState(iDeviceState); + } r = (*iEnablePullUpOnDPlus)(iOtgContext); if (r != KErrNone) { diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/drivers/usbcsc/d_usbcsc.cpp --- a/kernel/eka/drivers/usbcsc/d_usbcsc.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/drivers/usbcsc/d_usbcsc.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1208,6 +1208,7 @@ __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::~DLddUsbcScChannel()")); if (iController) { + iController->DeRegisterClient(this); iStatusCallbackInfo.Cancel(); iEndpointStatusCallbackInfo.Cancel(); iOtgFeatureCallbackInfo.Cancel(); @@ -1218,7 +1219,6 @@ iController->ReleaseDeviceControl(this); iOwnsDeviceControl = EFalse; } - iController->DeRegisterClient(this); iController=NULL; DestroyEp0(); if (iStatusFifo!=NULL) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/eabi/econs.def --- a/kernel/eka/eabi/econs.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/eabi/econs.def Sat Feb 20 00:10:51 2010 +0200 @@ -31,4 +31,5 @@ _ZNK8RConsole10ScreenSizeER5TSize @ 30 NONAME ; RConsole::ScreenSize(TSize&) const _ZNK8RConsole4SizeER5TSize @ 31 NONAME ; RConsole::Size(TSize&) const _ZNK8RConsole9CursorPosER6TPoint @ 32 NONAME ; RConsole::CursorPos(TPoint&) const + _ZNK11TConsoleKey13PointerNumberEv @ 33 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/eabi/ekernsmp.def --- a/kernel/eka/eabi/ekernsmp.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/eabi/ekernsmp.def Sat Feb 20 00:10:51 2010 +0200 @@ -1175,4 +1175,9 @@ _ZN4Kern19UnmapAndUnpinMemoryEP16TKernelMapObject @ 1174 NONAME _ZN4Kern21CreateKernelMapObjectERP16TKernelMapObjectj @ 1175 NONAME _ZN4Kern22DestroyKernelMapObjectERP16TKernelMapObject @ 1176 NONAME + _ZN9Interrupt16AddTimingEntropyEv @ 1177 NONAME + _ZN4Kern10RandomSaltEmj @ 1178 NONAME + _ZN4Kern10RandomSaltEyj @ 1179 NONAME + _ZN4Kern10RandomSaltEPKhjj @ 1180 NONAME + _ZN4Kern12SecureRandomER5TDes8 @ 1181 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/eabi/ekernu.def --- a/kernel/eka/eabi/ekernu.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/eabi/ekernu.def Sat Feb 20 00:10:51 2010 +0200 @@ -1166,4 +1166,9 @@ _ZN4Kern19UnmapAndUnpinMemoryEP16TKernelMapObject @ 1165 NONAME _ZN4Kern21CreateKernelMapObjectERP16TKernelMapObjectj @ 1166 NONAME _ZN4Kern22DestroyKernelMapObjectERP16TKernelMapObject @ 1167 NONAME + _ZN9Interrupt16AddTimingEntropyEv @ 1168 NONAME + _ZN4Kern10RandomSaltEmj @ 1169 NONAME + _ZN4Kern10RandomSaltEyj @ 1170 NONAME + _ZN4Kern10RandomSaltEPKhjj @ 1171 NONAME + _ZN4Kern12SecureRandomER5TDes8 @ 1172 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/eabi/euseru.def --- a/kernel/eka/eabi/euseru.def Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/eabi/euseru.def Sat Feb 20 00:10:51 2010 +0200 @@ -2501,4 +2501,7 @@ _ZN15TExtendedLocale10LoadLocaleERK7TDesC16S2_S2_ @ 2500 NONAME _ZN15TExtendedLocale16LoadLocaleAspectERK7TDesC16 @ 2501 NONAME _ZN16TChunkCreateInfo11SetReadOnlyEv @ 2502 NONAME + _ZN4Math7RandomLER5TDes8 @ 2503 NONAME + _ZN4Math6RandomER5TDes8 @ 2504 NONAME + _ZN4Math7RandomLEv @ 2505 NONAME diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/euser/us_exec.cpp --- a/kernel/eka/euser/us_exec.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/euser/us_exec.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -6358,7 +6358,14 @@ EXPORT_C TUint32 Math::Random() /** -Gets 32 random bits from the kernel's random pool. +Gets 32 random bits from the kernel's random number generator. + +The returned random data may or may not be cryptographically secure but should be of a high quality for +non-cryptographic purposes. + +This function uses a cryptographically strong random number generator to generate the random data, which can +be slower than insecure generators. If security is not important, a faster generator may be used such as +Math::Rand(). @return The 32 random bits. */ @@ -6367,6 +6374,62 @@ return Exec::MathRandom(); } +EXPORT_C void Math::Random(TDes8& aRandomValue) +/** +Fills the provided descriptor with random data up to its current length. The number of random bytes required +should be specified by setting the length of the descriptor that is passed to this function. + +The returned random data may or may not be cryptographically secure but should be of a high quality for +non-cryptographic purposes. + +This function uses a cryptographically strong random number generator to generate the random data, which can +be slower than insecure generators. If security is not important, a faster generator may be used such as +Math::Rand(). + +@param aRandomValue on return, the descriptor is filled with the requested number of random bytes. +*/ + { + Exec::MathSecureRandom(aRandomValue); + } + + +EXPORT_C void Math::RandomL(TDes8& aRandomValue) +/** +Fills the provided descriptor with random data up to its current length. The number of random bytes required +should be specified by setting the length of the descriptor that is passed to the function. + +If the returned random data cannot be guaranteed to be cryptographically secure, the function will leave with +KErrNotReady to indicate that the returned data should not be used for cryptographic purposes. + +The security strength of the cryptographically strong random number generator is 256 bits. + +@param aRandomValue on return, the descriptor is filled with the requested number of random bytes. + +@leave KErrNotReady if the returned random data cannot be guaranteed to be cryptographically secure. +*/ + { + User::LeaveIfError(Exec::MathSecureRandom(aRandomValue)); + } + +EXPORT_C TUint32 Math::RandomL() +/** +Gets 32 random bits from the kernel's random number generator. + +If the returned random data could not be guaranteed to be cryptographically secure, the function will instead +leave with KErrNotReady to indicate that data was not available. + +The security strength of the cryptographically strong random number generator is 256 bits. + +@leave KErrNotReady if no data was returned as it could not be guaranteed to be cryptographically secure. + +@return The 32 random bits. +*/ + { + TBuf8 randomBuffer; + randomBuffer.SetMax(); + User::LeaveIfError(Exec::MathSecureRandom(randomBuffer)); + return *(TUint32*)(randomBuffer.Ptr()); + } EXPORT_C void User::IMB_Range(TAny* aStart, TAny* aEnd) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/ewsrv/co_utl.cpp --- a/kernel/eka/ewsrv/co_utl.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/ewsrv/co_utl.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -44,6 +44,14 @@ return((*((TConsoleKey *)this))().iModifiers); } +EXPORT_C TUint8 TConsoleKey::PointerNumber() const +// +// Return the pointer number +// + { + return((*((TConsoleKey *)this))().iPointerNumber); + } + EXPORT_C TInt TConsoleKey::Type() const // // Return the key type diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/ewsrv/ws_win.cpp --- a/kernel/eka/ewsrv/ws_win.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/ewsrv/ws_win.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -2170,6 +2170,7 @@ case TRawEvent::EButton3Down: case TRawEvent::EButton3Up: pS->iMousePos=anEvent.Pos(); + pS->iPointerNumber = anEvent.PointerNumber(); break; case TRawEvent::EKeyUp: case TRawEvent::EKeyDown: @@ -2433,6 +2434,7 @@ k.iModifiers=KeyTranslator->GetModifierState(); + k.iPointerNumber = pS->iPointerNumber; k.iType=pS->iType; k.iMousePos=pS->iMousePos; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/generic.inf --- a/kernel/eka/generic.inf Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/generic.inf Sat Feb 20 00:10:51 2010 +0200 @@ -22,9 +22,9 @@ start extension base/genexec #ifdef SYMBIAN_OLD_EXPORT_LOCATION -option INC_PATH /epoc32/include +option INC_PATH $(EPOCROOT)epoc32/include #else -option INC_PATH /epoc32/include/platform +option INC_PATH $(EPOCROOT)epoc32/include/platform #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/drivers/sdcard.h --- a/kernel/eka/include/drivers/sdcard.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/drivers/sdcard.h Sat Feb 20 00:10:51 2010 +0200 @@ -151,7 +151,7 @@ IMPORT_C virtual TMMCErr AcquireStackSM(); IMPORT_C virtual TMMCErr CIMReadWriteBlocksSM(); IMPORT_C virtual DMMCSession* AllocSession(const TMMCCallBack& aCallBack) const; - + virtual void AddressCard(TInt aCardNumber) = 0; inline TSDCardArray& CardArray() const; @@ -175,8 +175,10 @@ private: TInt iSpare; +protected: enum TSDCardType {ESDCardTypeUnknown, ESDCardTypeIsMMC, ESDCardTypeIsSD}; TSDCardType iCxCardType; // Used when detecting whether an SD Memory card is present. +private: TUint8 iACMD22[KSDACMD22BlockLen]; private: @@ -185,7 +187,11 @@ IMPORT_C virtual void Dummy1(); IMPORT_C virtual void Dummy2(); IMPORT_C virtual void Dummy3(); - IMPORT_C virtual void Dummy4(); + +public: + IMPORT_C virtual DSDStack::TSDCardType CardType(TInt aSocket, TInt aCardNumber); + +private: // // Reserved members to maintain binary compatibility TInt iReserved[68]; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/drivers/usbcshared.h --- a/kernel/eka/include/drivers/usbcshared.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/drivers/usbcshared.h Sat Feb 20 00:10:51 2010 +0200 @@ -1598,6 +1598,7 @@ NTimer iReconnectTimer; // implements USB re-enumeration delay NTimer iCableStatusTimer; // implements USB cable status detection delay DUsbcPowerHandler* iPowerHandler; // pointer to USB power handler object + TSpinLock iUsbLock; // implement SMP for USB PDD and LDD protected: TDfc iPowerUpDfc; // queued by power handler upon power-up diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/drivers/usbcshared.inl --- a/kernel/eka/include/drivers/usbcshared.inl Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/drivers/usbcshared.inl Sat Feb 20 00:10:51 2010 +0200 @@ -132,72 +132,72 @@ TBool DUsbClientController::IsInTheRequestList(const TUsbcRequestCallback& aCallback) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEp0ReadRequestCallbacks); TUsbcRequestCallback* p; while ((p = iter++) != NULL) { if (p == &aCallback) { - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return ETrue; } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return EFalse; } TBool DUsbClientController::IsInTheStatusList(const TUsbcStatusCallback& aCallback) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iStatusCallbacks); TUsbcStatusCallback* p; while ((p = iter++) != NULL) { if (p == &aCallback) { - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return ETrue; } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return EFalse; } TBool DUsbClientController::IsInTheEpStatusList(const TUsbcEndpointStatusCallback& aCallback) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iEpStatusCallbacks); TUsbcEndpointStatusCallback* p; while ((p = iter++) != NULL) { if (p == &aCallback) { - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return ETrue; } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return EFalse; } TBool DUsbClientController::IsInTheOtgFeatureList(const TUsbcOtgFeatureCallback& aCallback) { - const TInt irq = NKern::DisableAllInterrupts(); + const TInt irq = __SPIN_LOCK_IRQSAVE(iUsbLock); TSglQueIter iter(iOtgCallbacks); TUsbcOtgFeatureCallback* p; while ((p = iter++) != NULL) { if (p == &aCallback) { - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return ETrue; } } - NKern::RestoreInterrupts(irq); + __SPIN_UNLOCK_IRQRESTORE(iUsbLock, irq); return EFalse; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/e32kpan.h --- a/kernel/eka/include/e32kpan.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/e32kpan.h Sat Feb 20 00:10:51 2010 +0200 @@ -503,6 +503,11 @@ An invalid parameter was passed to a shared buffers exec call handler. */ EShBufExecBadParameter=65, + + /** + An entropy estimate passed to an entropy buffer was outside the allowed range. + */ + EEntropyEstimateOutOfRange=66, }; #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/e32math.h --- a/kernel/eka/include/e32math.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/e32math.h Sat Feb 20 00:10:51 2010 +0200 @@ -475,6 +475,9 @@ IMPORT_C static TInt Rand(TInt64 &aSeed); IMPORT_C static TReal FRand(TInt64 &aSeed) __SOFTFP; IMPORT_C static TUint32 Random(); + IMPORT_C static void Random(TDes8& aRandomValue); + IMPORT_C static void RandomL(TDes8& aRandomValue); + IMPORT_C static TUint32 RandomL(); IMPORT_C static TInt Round(TReal &aTrg,const TReal &aSrc,TInt aDecimalPlaces); IMPORT_C static TInt Sin(TReal &aTrg,const TReal &aSrc); IMPORT_C static TInt Sqrt(TReal &aTrg,const TReal &aSrc); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/e32twin.h --- a/kernel/eka/include/e32twin.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/e32twin.h Sat Feb 20 00:10:51 2010 +0200 @@ -56,6 +56,7 @@ TUint iModifiers; TPoint iMousePos; TInt iType; + TUint8 iPointerNumber; }; /** @internalTechnology */ @@ -66,6 +67,7 @@ IMPORT_C TInt Modifiers() const; IMPORT_C TInt Type() const; IMPORT_C TPoint MousePos() const; + IMPORT_C TUint8 PointerNumber() const; }; /** @internalTechnology */ diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/e32ver.h --- a/kernel/eka/include/e32ver.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/e32ver.h Sat Feb 20 00:10:51 2010 +0200 @@ -28,7 +28,7 @@ const TInt KE32MajorVersionNumber=2; const TInt KE32MinorVersionNumber=0; -const TInt KE32BuildVersionNumber=2066; +const TInt KE32BuildVersionNumber=2075; const TInt KMachineConfigurationMajorVersionNumber=1; const TInt KMachineConfigurationMinorVersionNumber=0; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/arm/assp.h --- a/kernel/eka/include/kernel/arm/assp.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/arm/assp.h Sat Feb 20 00:10:51 2010 +0200 @@ -38,9 +38,10 @@ A class that exports interrupt functionality to device drivers and other kernel-side code. -Although Symbian OS defines this class, it does not implement it; -an implementation for each of the functions defined by this class must -be provided by the Variant in the baseport. +Although Symbian OS defines this class, it does not implement the majority +of it; an implementation for each of the functions defined by this class, +with the exception of AddTimingEntropy, must be provided by the Variant in +the baseport. Note that the class only provides the public API for using interrupts, not for dispatching them. @@ -142,6 +143,16 @@ are not supported. */ IMPORT_C static TInt SetPriority(TInt anId, TInt aPriority); + + /** + This function is implemented by the kernel. It adds the current, highest + resolution timestamp to the secure RNG's entropy pool. + + It should be called from the ISR of any device where the timing of interrupts + would be considered random, for example the keyboard or digitiser drivers. + */ + + IMPORT_C static void AddTimingEntropy(); }; /** diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/arm/bootdefs.h --- a/kernel/eka/include/kernel/arm/bootdefs.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/arm/bootdefs.h Sat Feb 20 00:10:51 2010 +0200 @@ -138,12 +138,16 @@ /** The most common values for BPR_Platform_Specific_Mappings boot parameter. Any *_Mapping5 value can be orred with any -*_Mapping6 or *_Mapping7. For example: +*_Mapping6 and/or *_Mapping7. For example: @code ParameterTable - DCD BPR_Platform_Specific_Mappings, E_WT_WT_Mapping5 | E_FC_NC_Mapping6 | E_NC_FC_Mapping7 + DCD BPR_Platform_Specific_Mappings, E_WT_WT_Mapping5+E_FC_NC_Mapping6+E_NC_FC_Mapping7 @codeend -Where stated, "maximum caching" refers to write back read/write allocate if supported by platform. +specifies: + - EMemAttPlatformSpecific5 to be write-through mapping in both inner and outer cache. + - EMemAttPlatformSpecific6 to be fully cached (write-back) in inner cache and not cached in outer cache. + - EMemAttPlatformSpecific7 to be not cached in inner cache and fully cached (write-back) in outer cache. + @see BPR_Platform_Specific_Mappings @publishedPartner @released @@ -151,14 +155,20 @@ enum TPlatformSpecificMappings { E_WT_WT_Mapping5 = 0x08000802, /**Write Through caching on both levels for mapping #5.*/ + E_WT_NC_Mapping5 = 0x00000802, /**Write Through caching at level 1, not cached at level 2 for mapping #5.*/ + E_NC_WT_Mapping5 = 0x08000002, /**Not cached at level 1, Write Through cached at level for mapping #5.*/ E_FC_NC_Mapping5 = 0x00000402, /**Maximum caching at level 1, not cached at level 2 for mapping #5.*/ E_NC_FC_Mapping5 = 0x04000002, /**Not cached at level 1, maximum caching at level 2 for mapping #5.*/ E_WT_WT_Mapping6 = 0x20002008, /**Write Through caching on both levels for mapping #6.*/ + E_WT_NC_Mapping6 = 0x00002008, /**Write Through caching at level 1, not cached at level 2 for mapping #6.*/ + E_NC_WT_Mapping6 = 0x20000008, /**Not cached at level 1, Write Through cached at level for mapping #6.*/ E_FC_NC_Mapping6 = 0x00001008, /**Maximum caching at level 1, not cached at level 2 for mapping #6.*/ E_NC_FC_Mapping6 = 0x10000008, /**Not cached at level 1, maximum caching at level 2 for mapping #6.*/ E_WT_WT_Mapping7 = 0x80008020, /**Write Through caching on both levels for mapping #7.*/ + E_WT_NC_Mapping7 = 0x00008020, /**Write Through caching at level 1, not cached at level 2 for mapping #7.*/ + E_NC_WT_Mapping7 = 0x80000020, /**Not cached at level 1, Write Through cached at level for mapping #7.*/ E_FC_NC_Mapping7 = 0x00004020, /**Maximum caching at level 1, not cached at level 2 for mapping #7.*/ E_NC_FC_Mapping7 = 0x40000020, /**Not cached at level 1, maximum caching at level 2 for mapping #7.*/ }; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/cache_maintenance.h --- a/kernel/eka/include/kernel/cache_maintenance.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/cache_maintenance.h Sat Feb 20 00:10:51 2010 +0200 @@ -43,6 +43,12 @@ const TInt KCacheInfoD=1; // InternalCache info for DCache. On ARMv7, this applies to the point-of-coherency. const TInt KCacheInfoD_PoU=2; // InternalCache info for ARMv7 DCache for the point-of-unification. +#if !defined(__CPU_MEMORY_TYPE_REMAPPING) && defined(__CPU_ARM) +// These constants must be dthe same as DefaultPRRR & DefaultNMRR in bootcpu.inc +const TUint32 KDefaultPrimaryRegionRemapRegister = 0x000a00a4; +const TUint32 KDefaultNormalMemoryRemapRegister = 0x00400040; +#endif + /* * Cache info of particular cache type or level. */ @@ -100,7 +106,6 @@ /* * @return Internal and external cache attributes (orred TMappingAttributes enums) * that match aType memory type. - * @panic: If aType 4-7 is specified on platform with no __CPU_MEMORY_TYPE_REMAPPING. */ static TUint32 TypeToCachingAttributes(TMemoryType aType); @@ -323,7 +328,6 @@ static void ParseCacheSizeInfo(TUint32 aValue, SCacheInfo& aInfo); #endif -#if defined(__CPU_MEMORY_TYPE_REMAPPING) /* * @return The content of Primary Region Remap Register. */ @@ -333,11 +337,18 @@ * @return The content of Normal Memory Remap Register. */ static TUint32 NormalMemoryRemapRegister(); -#endif // defined(__CPU_MEMORY_TYPE_REMAPPING) #if defined(__CPU_ARMV7) static TInt DmaBufferAlignementLog2; // Holds the alignement requirement for DMA buffers. #endif + +#if !defined(__CPU_MEMORY_TYPE_REMAPPING) && defined(__CPU_ARM) + /** + * On platforms with no memory type remapping, we have to simulate TMemoryType values 4-7 + */ + static TUint32 iPrimaryRegionRemapRegister; + static TUint32 iNormalMemoryRemapRegister; +#endif }; #ifdef __HAS_EXTERNAL_CACHE__ diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/kern_priv.h --- a/kernel/eka/include/kernel/kern_priv.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/kern_priv.h Sat Feb 20 00:10:51 2010 +0200 @@ -62,6 +62,9 @@ #endif #endif +// size of each buffer used to store entropy data before it is passed to the RNG +const TUint KEntropyBufferSizeWords = 1024;// maximum size of 1024 words (32Kbit); + const TInt KKernelServerDefaultPriority=16; const TInt KDefaultExitPriority=KKernelServerDefaultPriority; @@ -2482,6 +2485,9 @@ ECodeSegRemoveAbsent=135, EPhysicalPinObjectBad=136, EShBufVirtualNotDefined=137, //< A required virtual method is not present in a shared buffer derived class (internal error) + ESecureRNGInitializationFailed = 138, + ESecureRNGInternalStateNotSecure = 139, + ESecureRNGOutputsInBadState = 140, ESystemException=0x10000000, ESoftwareWarmReset=0x10000001 @@ -2562,6 +2568,10 @@ static TKernelHookFn KernelHooks[ENumKernelHooks]; static TMiscNotifierMgr TheMiscNotifierMgr; static TAny* VariantData[31]; + static TUint32 EntropyBufferStatus[KMaxCpus]; + static TUint32* EntropyBuffer[KMaxCpus]; + static TUint32 TempEntropyBuffer[KEntropyBufferSizeWords]; + static TDfc EntropyBufferDfc; public: static TInt InitialiseMicrokernel(); #ifdef __SMP__ @@ -2754,6 +2764,7 @@ static void Init2AP(); #endif static void Init3(); + static void Init4(); static TInt InitSvHeapChunk(DChunk* aChunk, TInt aSize); static TInt InitSvStackChunk(); static TBool IsRomAddress(const TAny* aPtr); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/kern_test.h --- a/kernel/eka/include/kernel/kern_test.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/kern_test.h Sat Feb 20 00:10:51 2010 +0200 @@ -34,7 +34,8 @@ enum TTestFunction { EUserModeCallbackSleep, - EUserModeCallbackSpin, + EUserModeCallbackSpin, + ERNGReseedHook, }; IMPORT_C static TInt Test(TTestFunction aFunc, TAny* a1 = NULL, TAny* a2 = NULL, TAny* a3 = NULL); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/kernboot.h --- a/kernel/eka/include/kernel/kernboot.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/kernboot.h Sat Feb 20 00:10:51 2010 +0200 @@ -91,7 +91,8 @@ TUint32 iAPBootPageLin; /**< @internalComponent */ TUint32 iAPBootPageDirPhys; /**< @internalComponent */ TUint32 iSmrData; /**< address of shadow memory region information block (SMRIB), optional field set by bootstrap PSL */ - TInt iReserved[26]; /**< reserved for the future use*/ + TUint32 iPlatformSpecificMappings; + TInt iReserved[25]; /**< reserved for the future use*/ }; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/kernel.h --- a/kernel/eka/include/kernel/kernel.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/kernel.h Sat Feb 20 00:10:51 2010 +0200 @@ -250,6 +250,8 @@ const TUint8 KMutexOrdHandle = 0x30; /**< @internalComponent */ const TUint8 KMutexOrdObjectCon = 0x28; /**< @internalComponent */ const TUint8 KMutexOrdMachineConfig = 0x20; /**< @internalComponent */ +const TUint8 KMutexOrdEntropyPool = 0x12; /**< @internalComponent */ +const TUint8 KMutexOrdRandNumGeneration = 0x11; /**< @internalComponent */ const TUint8 KMutexOrdHwChunk = 0x10; /**< @internalComponent */ const TUint8 KMutexOrdKernelHeap = 0x08; /**< @internalComponent */ const TUint8 KMutexOrdRamAlloc = 0x04; /**< @internalComponent */ @@ -1011,7 +1013,11 @@ IMPORT_C static TSuperPage& SuperPage(); IMPORT_C static TMachineConfig& MachineConfig(); IMPORT_C static TUint32 Random(); - IMPORT_C static void RandomSalt(TUint32 aBit); + IMPORT_C static void RandomSalt(TUint32 aEntropyData); + IMPORT_C static void RandomSalt(TUint32 aEntropyData, TUint aBitsOfEntropy); + IMPORT_C static void RandomSalt(TUint64 aEntropyData, TUint aBitsOfEntropy); + IMPORT_C static void RandomSalt(const TUint8* aEntropyData, TUint aEntropyDataLength, TUint aBitsOfEntropy); + IMPORT_C static TInt SecureRandom(TDes8& aRandomValue); IMPORT_C static void WaitForRequest(TRequestStatus& aStatus); /**< @internalTechnology */ IMPORT_C static TAny* Alloc(TInt aSize); IMPORT_C static TAny* AllocZ(TInt aSize); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/securerng.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/kernel/securerng.h Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,120 @@ +// Copyright (c) 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: +// eka\include\kernel\securerng.h +// +// + +/** + @file + @internalTechnology +*/ + +#ifndef __SECURERNG_H__ +#define __SECURERNG_H__ + +#include +#include +#include "sha256.h" + +//Constants required for Secure RNG + +// Specifies the maximum number of random requests that can be served with a single secure internal state or seed. +// NIST recommends this value to be significantly less than 2^48 for all practical usage. The factors affecting the chosen value are +// 1> This value should not be too high as it may weaken the strength of the random numbers generated after certain requests. +// 2> Should be able to expose if any problems in the entropy Accumulation and Reseed unit at the earliest. +// 3> Also depends on the number of entropy sources contributing the entropy data. +const TUint32 KReseedInterval = 16777216; //is equal to 2^24 +// 8 (for 01) + 440 (for V) + 256 (for the hashed entropy input) + 64 (for personilazation string) => 768 / 8 = 96. +const TUint KMaxSeedMaterialLength = 96; +// Entropy pool threshold for reseed = HASH_DRBG security strength(256) +const TUint KReseedThreshold = 256; +// Entropy pool threshold for instantiation = HASH_DRBG security strength(256) + 1/2 of HASH_DRBG security strength(128) => 384 +const TUint KInstantiationThreshold = 384; +// Maximum number of random bytes that can be served by Secure RNG. Should be less than or equal to 2^19 = 524288 bits as per HASH_DRBG algorithm +const TInt KMaxNoOfRequestedBytes = 65536; // in bytes + +// SeedLength for Hash_DRBG is fixed to be 55 bytes as per Hash_DRBG Algorithm. +const TInt KSeedLength = 55; + +// SHA256 hash size in bytes +const TInt KSHA256OutLengthInBytes = 32; + +/** + *Utility functions for generating secure random numbers. +*/ +class DSecureRNG: public DBase + { +public: + DSecureRNG(); + + //Generates the requested number of random bits + TInt GenerateRandomNumber(TDes8& aRandomValue); + void AddEntropy(const TUint8* aEntropy, TInt aLength, TInt aEstimation); + inline TBool SecureRNGIdle() {return iSecureRNGIdle;} + void SetReseedHook(void (*aHookFn)(TAny*), TAny* aHookArg); + +private: + void HashGen(TDes8& aRandomValue); + void Reseed(const TDesC8& aEntropyInput); + void AddBigNumberToInternalStateV(const TUint8* aInteger2, TInt aLength); + void HashDf(const TDesC8& aInputData, TUint8* aOutputData); + + inline void IncrementData(TDes8& aData); + inline TUint32 ConvertToBigEndian(TUint32 aTempCounter); + inline const TUint8* HashDataAndCompare(TDes8& aData); + +private: + // Mutex to enforce concurrency control over the system internal states and other related members + DMutex* iSecureRNGMutex; + + // Mutex to enforce concurrency control over the entropy pool and entropy estimation + DMutex* iEntropyMutex; + + SHA256 iSha256; + + // Object acts as a entropy pool to hold the entropy inputs in hash context. + SHA256 iEntropyPool; + + // Internal_State_V and Internal_State_C are secret values of Hash DRBG mechanism + TUint8 iInternalStateV[KSeedLength]; + TUint8 iInternalStateC[KSeedLength]; + + // Required for comparision during continous random number generation test + TBuf8 iCompareBuffer; + + // Counts how many random requests are served since last reseed. + TUint32 iReseedCounter; + + // Cumulative estimation of the so far collected entropy inputs in the pool. + TUint32 iEntropyEstimation; + + // Holds system's current operational status (Idle / Active). + volatile TBool iSecureRNGIdle; + + // Says whether the system is secure or not at the moment. + TBool iRNGSecure; + + // Estimation threshold limit, decides the reseed invocation point. + TUint32 iEntropyThreshold; + + // Hook to call on reseed + void (*iReseedHookFn)(TAny*); + TAny* iReseedHookArg; + }; + +// The secure random number generator - global object. +extern DSecureRNG *SecureRNG; + +#endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/sha256.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/kernel/sha256.h Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,63 @@ +/** +* Copyright (c) 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: +* kernel/eka/include +* +*/ +/** + @file + @internalTechnology + */ + +#ifndef __SHA256_H__ +#define __SHA256_H__ + +#include +#include +#include + + +const TUint KSHA256BlockSize = 64; +const TInt KSHA256HashSize = 32; + +class SHA256 + { +public: + SHA256(); // constructor + void Reset(); + const TDesC8& Final(void); + void Update(const TUint8* aData,TUint aLength); + +private: + inline void AddLength(const TUint aLength); + inline void CopyWordToHash(TUint aVal, TInt aIndex); + void Block(); + void PadMessage(); + +private: + TBuf8 iHash; + TUint iA; + TUint iB; + TUint iC; + TUint iD; + TUint iE; + TUint iF; + TUint iG; + TUint iH; + TUint iData[KSHA256BlockSize]; + TUint iNl; + TUint64 iNh; + }; + +#endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/kernel/x86/assp.h --- a/kernel/eka/include/kernel/x86/assp.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/kernel/x86/assp.h Sat Feb 20 00:10:51 2010 +0200 @@ -40,9 +40,10 @@ A class that exports interrupt functionality to device drivers and other kernel-side code. -Although Symbian OS defines this class, it does not implement it; -an implementation for each of the functions defined by this class must -be provided by the Variant in the baseport. +Although Symbian OS defines this class, it does not implement the majority +of it; an implementation for each of the functions defined by this class, +with the exception of AddTimingEntropy, must be provided by the Variant in +the baseport. Note that the class only provides the public API for using interrupts, not for dispatching them. @@ -145,6 +146,16 @@ are not supported. */ IMPORT_C static TInt SetPriority(TInt anId, TInt aPriority); + + /** + This function is implemented by the kernel. It adds the current, highest + resolution timestamp to the secure RNG's entropy pool. + + It should be called from the ISR of any device where the timing of interrupts + would be considered random, for example the keyboard or digitiser drivers. + */ + + IMPORT_C static void AddTimingEntropy(); }; struct SInterruptHandler diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/include/ws_std.h --- a/kernel/eka/include/ws_std.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/include/ws_std.h Sat Feb 20 00:10:51 2010 +0200 @@ -79,6 +79,7 @@ { TKeyData iKeyData; TInt iType; + TUint8 iPointerNumber; TPoint iMousePos; TSglQueLink iLink; }; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/arm/bootmain.s --- a/kernel/eka/kernel/arm/bootmain.s Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/arm/bootmain.s Sat Feb 20 00:10:51 2010 +0200 @@ -1299,7 +1299,16 @@ ENDIF ; CFG_MMUPresent ENDIF ; CFG_DebugBootRom - + IF :LNOT: CFG_MemoryTypeRemapping + ; Pass BPR_Platform_Specific_Mappings to Kernel on platforms + ; with no memory type remapping feature. Kernel will emulate them + ; in order to support TMemoryType values 4-7 + MOV r0, #BPR_Platform_Specific_Mappings + BOOTCALL BTF_Params ; r0 = BPR_Platform_Specific_Mappings + MOVMI r0, #0 ; r0 = 0, if parameter not defined in table. + STR r0, [r10, #SSuperPageBase_iPlatformSpecificMappings] + ENDIF + IF :DEF: CFG_HasL210Cache ;Enable L2 cache. Enabling L220 & PL310 is baseport specific due to security extension (TrustZone). LDR r0, [r10, #SSuperPageBase_iArmL2CacheBase] diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/arm/cache_external.cpp --- a/kernel/eka/kernel/arm/cache_external.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/arm/cache_external.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -136,9 +136,14 @@ * different master ports. * Status: * Not fixed in Kernel as there is no software workaround for this erratum. + * + * - 727915: Background Clean & Invalidate by Way operation can cause data corruption + * Status: + * There was no need to fix anything as PL310 cache maintenance doesn't use any + * _Maintain_ByWay operation. (It is only used in ExternalCache::AtomicSync on + * L210 & L220.) */ - #include #include "cache_maintenance.h" #include @@ -314,6 +319,7 @@ #if defined(__ARM_PL310_CACHE__) // On Pl310, we hold the lock while maintaining cache. Therefore, we cannot // do that on a way basis as it takes too long to complete. + // This will also ensure that PL310 erratum 727915 is sorted out. #if defined(__ARM_PL310_ERRATUM_588369_FIXED) Maintain_All((TInt*)(Base+ARML2C_CleanInvalidateByIndexWay)); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/arm/cache_maintenance.cpp --- a/kernel/eka/kernel/arm/cache_maintenance.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/arm/cache_maintenance.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -31,6 +31,12 @@ TInt InternalCache::DmaBufferAlignementLog2; #endif +#if !defined(__CPU_MEMORY_TYPE_REMAPPING) +TUint32 InternalCache::iPrimaryRegionRemapRegister; +TUint32 InternalCache::iNormalMemoryRemapRegister; +#endif + + void CacheMaintenance::Init1() { InternalCache::Init1(); @@ -826,8 +832,27 @@ __KTRACE_OPT(KBOOT,Kern::Printf("DCache:\n")); DumpCacheInfo(Info[KCacheInfoD]); #endif +#if !defined(__CPU_MEMORY_TYPE_REMAPPING) + // Simulate PRRR & NRRR MMU registers on platforms without memory remap feature. + // "Magic" numbers come from the description of ARM core's remap registers. + TUint32 platformSpecificMappings = TheSuperPage().iPlatformSpecificMappings; + iPrimaryRegionRemapRegister = KDefaultPrimaryRegionRemapRegister | ((platformSpecificMappings&0x3f)<<10); + iNormalMemoryRemapRegister = KDefaultNormalMemoryRemapRegister | (platformSpecificMappings&0xfc00fc00); +#endif //!defined(__CPU_MEMORY_TYPE_REMAPPING) } +#if !defined(__CPU_MEMORY_TYPE_REMAPPING) +TUint32 InternalCache::PrimaryRegionRemapRegister() + { + return iPrimaryRegionRemapRegister; + } + +TUint32 InternalCache::NormalMemoryRemapRegister() + { + return iNormalMemoryRemapRegister; + } +#endif //!defined(__CPU_MEMORY_TYPE_REMAPPING) + #endif //else defined(__CPU_ARMV7) #ifdef __BROADCAST_CACHE_MAINTENANCE__ @@ -995,8 +1020,7 @@ TUint32 InternalCache::TypeToCachingAttributes(TMemoryType aType) - { - + { TUint32 attr = 0; switch (aType) { @@ -1010,7 +1034,6 @@ case EMemAttPlatformSpecific6: case EMemAttPlatformSpecific7: { - #if defined(__CPU_MEMORY_TYPE_REMAPPING) // The mapping of these types are defined in bootstrap. // Read remap registers and set mapping attributes accordingly. // "Magic" numbers come from the description of ARM core's remap registers. @@ -1044,9 +1067,6 @@ default: CACHEFAULT(); //unsupported value (3) in Primary Region Remap Register } - #else //defined(__CPU_MEMORY_TYPE_REMAPPING) - CACHEFAULT(); // memory types 4-7 are not supported on these platforms - #endif } break; default: diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/ekern.mmp --- a/kernel/eka/kernel/ekern.mmp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/ekern.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -139,6 +139,7 @@ source sexec.cpp sinit.cpp skernel.cpp source scodeseg.cpp sipc.cpp notifier.cpp source object.cpp power.cpp server.cpp +source sha256.cpp securerng.cpp source stimer.cpp sutils.cpp random.cpp source sprocess.cpp sthread.cpp source smqueue.cpp @@ -150,6 +151,7 @@ source sbtrace.cpp source stest.cpp source sshbuf.cpp smap.cpp +source srandombuff.cpp sourcepath ../klib source dbase.cpp kdes8.cpp diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/execs.txt --- a/kernel/eka/kernel/execs.txt Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/execs.txt Sat Feb 20 00:10:51 2010 +0200 @@ -640,7 +640,6 @@ name = MathRandom return = TUint32 kernel = Kern::Random - lock } slow { @@ -2431,6 +2430,14 @@ norelease } + +slow { + name = MathSecureRandom + return = TInt + arg1 = TDes8& +} + + /****************************************************************************** * End of normal executive functions ******************************************************************************/ @@ -2461,3 +2468,4 @@ return = TInt } + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/random.cpp --- a/kernel/eka/kernel/random.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/random.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -16,52 +16,23 @@ // #include - -// -// Generate nth random number using the following algorithm -// -// X[n] = ((X[n-j] rotl r1) + (X[n-k] rotl r2)) modulo 2^b -// -// k=17, j=10, r1=5, r2=3 -// - -const TInt KBufferSize=17; -const TInt KBufferSizeInBits=KBufferSize*32; -const TInt KPointer2Offset=10; // Must be less than KBufferSize - -TUint32 RandomBuffer[KBufferSize]; -TInt RandomPointer=1; -TInt RandomSaltPointer=KBufferSizeInBits-1; - -inline TUint32 RotateLeft5(TUint32 aVal) - { return (aVal << 5) | (aVal >> 27); } +#include "securerng.h" +#include "execs.h" -inline TUint32 RotateLeft3(TUint32 aVal) - { return (aVal << 3) | (aVal >> 29); } - -void K::Randomize() -// -// Initialise the random pool -// - { - TUint64 seed=K::TickQ->iRtc; - TInt i; - for (i=0; i>59)) + 97; - } - NKern::LockSystem(); - for (i=0; i<50; i++) - Kern::Random(); - NKern::UnlockSystem(); - } - +// The global pointer to the RNG instance +DSecureRNG* SecureRNG; /** - Generate the next random number. + Gets 32 random bits from the kernel's random number generator. + + The returned random data may or may not be cryptographically secure but should be of a high quality for + non-cryptographic purposes. - @return The generated random number. + This function uses a cryptographically strong random number generator to generate the random data, which can + be slower than insecure generators. If security is not important, you may wish to use a trivial RNG instead + for performance. + + @return The 32 random bits. @pre Kernel Lock must not be held. @pre No fast mutex should be held @@ -70,42 +41,116 @@ */ EXPORT_C TUint32 Kern::Random() { - TBool alreadyLocked = TheScheduler.iLock.HeldByCurrentThread(); - if (!alreadyLocked) - NKern::LockSystem(); - TInt p1 = RandomPointer; - if(--p1<0) - p1 = KBufferSize-1; - RandomPointer = p1; - TInt p2 = p1+KPointer2Offset; - if(p2>KBufferSize-1) - p2 -= KBufferSize-1; - TUint32 r = RandomBuffer[p1] = RotateLeft5(RandomBuffer[p2])+RotateLeft3(RandomBuffer[p1]); - if (!alreadyLocked) - NKern::UnlockSystem(); - return r; + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD, "Kern::Random()"); + TBuf8<4> randomBuffer; + randomBuffer.SetMax(); + SecureRNG->GenerateRandomNumber(randomBuffer); + return *((const TUint32*)randomBuffer.Ptr()); + } + +/** + Fills the provided descriptor with random data up to its current length. The number of random bytes required + should be specified by setting the length of the descriptor that is passed to the function. + + If the returned random data cannot be guaranteed to be cryptographically secure, the function will return + KErrNotReady, but data will still be provided suitable for non-cryptographic purposes. + + The security strength of the cryptograpically strong random number generator is 256 bits. + + @param aRandomValue on return, the descriptor is filled with the requested number of random bytes. + + @return KErrArgument if more than 65536 bytes are requested in a single call. + KErrNotReady if the returned random data cannot be guaranteed to be cryptographically secure. + KErrNone if the returned random data is believed to be cryptographically secure. + + @pre Kernel Lock must not be held + @pre No fast mutex should be held + @pre Interrupts should be enabled + @pre Can be used in a device driver. +*/ +EXPORT_C TInt Kern::SecureRandom(TDes8& aRandomValue) + { + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD, "Kern::SecureRandom(TDes8&)"); + return SecureRNG->GenerateRandomNumber(aRandomValue); } /** - Adds a bit to the random pool used to generate random numbers. - This method should be used by any sources of entropy to improve the quality of - random number generation. + Adds the given entropy input to the entropy pool used for random number generation. + This is the only version of Kern::RandomSalt which allows entropy samples larger than 8 bytes to be added. + + Entropy estimates should be chosen carefully to reflect the minimum entropy that the sample may contain. - @param aBitOfSalt The least significant bit of this value is added to the random pool. + @param aEntropyData Pointer to the entropy data. + @param aEntropyDataLength Length of the entropy data in bytes. + @param aBitsOfEntropy The amount of entropy (in bits) present in the entropy data. - @pre Can be used in a device driver. + @pre Kernel Lock must not be held + @pre No fast mutex should be held + @pre Interrupts should be enabled + @pre Can be used in a device driver. */ -EXPORT_C void Kern::RandomSalt(TUint32 aBitOfSalt) +EXPORT_C void Kern::RandomSalt(const TUint8* aEntropyData, TUint aEntropyDataLength, TUint aBitsOfEntropy) { - TInt p=RandomSaltPointer; // protect RandomSaltPointer from re-entrantrancy - if (aBitOfSalt&=1) + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD, "Kern::RandomSalt(const TUint8*, TUint, TUint)"); + + // Check if the claimed entropy estimation (in bits) is not more than the maximum value. + __ASSERT_ALWAYS(aBitsOfEntropy <= aEntropyDataLength*8, K::PanicKernExec(EEntropyEstimateOutOfRange)); + + // If the Secure RNG system is not in idle mode, add the collected entropy to the entropy pool. + if (!SecureRNG->SecureRNGIdle()) { - TInt word=p >> 5; - TInt bit=p & 0x1f; - RandomBuffer[word] ^= aBitOfSalt << bit; + SecureRNG->AddEntropy(aEntropyData, aEntropyDataLength, aBitsOfEntropy); } - if (--p<0) - p=KBufferSizeInBits-1; - RandomSaltPointer=p; } +/* + * Exec handler function for obtaining secure random numbers + */ +TInt ExecHandler::MathSecureRandom(TDes8& aRandomValue) + { + TInt randomValueLength = 0; + TInt randomValueMaxLength = 0; + //Gets information about the user specified descriptor. + TUint8* kernelPtr = (TUint8*)Kern::KUDesInfo(aRandomValue, randomValueLength, randomValueMaxLength); + if(randomValueMaxLength == -1) //user passed descriptor is not writable + { + K::PanicKernExec(EKUDesSetLengthInvalidType); + } + + // The random number generator requires a temporary buffer to write the data to, before we write it back to + // userspace's buffer. The buffer is allocated here on the stack to avoid having to heap-allocate, and if + // the requested amount of data is larger, a loop is used. 2048 bytes will always fit onto the stack in an + // exec handler. + const TInt KRandomBufferSize = 2048; + TBuf8 randomBuffer; + + TInt err = KErrNone; + TBool isKErrNotReadyTrue = EFalse; + while(randomValueLength > 0) + { + TInt noOfBytesToGenerate = (randomValueLength > KRandomBufferSize) ? KRandomBufferSize : randomValueLength; + randomBuffer.SetLength(noOfBytesToGenerate); + // Generate random numbers + err = Kern::SecureRandom(randomBuffer); + if(err == KErrNotReady) + { + isKErrNotReadyTrue = ETrue; + } + else if (err != KErrNone) + { + return err; // any other system wide error code needs to be returned immediately. + } + // Copy the generated random numbers to the user descriptor. + umemput(kernelPtr, randomBuffer.Ptr(), noOfBytesToGenerate); + kernelPtr += KRandomBufferSize; + randomValueLength -= KRandomBufferSize; + } + + // Atleast one KErrNotReady error was generated during processing the request, so return the state as not ready + // indicating the internal states was not secure during random number generation. + if(isKErrNotReadyTrue) + { + return KErrNotReady; + } + return err; + } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/securerng.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/kernel/securerng.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,387 @@ +// Copyright (c) 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: +// eka\kernel\securerng.cpp +// +// + +#include "kernel/securerng.h" +#include "sha256.h" + +/** + * Default Constructor. + * Initialize the Secure RNG with values for iInternalStateV, iInternalStateC, Reseed_Counter + * Entropy Pool threshold and Secure RNG status + */ +DSecureRNG::DSecureRNG() : + iSha256(), + iEntropyPool(), + iReseedCounter(0), + iEntropyEstimation(0), + iSecureRNGIdle(EFalse), + iRNGSecure(EFalse), + iEntropyThreshold(KInstantiationThreshold) + { + // Create the Mutex objects before initializing the internal state. + _LIT(KRNGMutexName,"SecureRNGMutex"); + _LIT(KEntropyMutexName,"EntropyMutex"); + NKern::ThreadEnterCS(); + __ASSERT_ALWAYS(Kern::MutexCreate(iSecureRNGMutex, KRNGMutexName, KMutexOrdRandNumGeneration) == KErrNone, + K::Fault(K::ESecureRNGInitializationFailed)); + __ASSERT_ALWAYS(Kern::MutexCreate(iEntropyMutex, KEntropyMutexName, KMutexOrdEntropyPool) == KErrNone, + K::Fault(K::ESecureRNGInitializationFailed)); + NKern::ThreadLeaveCS(); + + // Initially feed the internal state with the current system time tick + TUint64 tick = Kern::SystemTimeSecure(); + TBuf8 entropyInput; + entropyInput.Copy((TUint8*)(&tick), sizeof(TUint64)); + + // Initialize the system internal state with the time tick as entropy input. + Reseed(entropyInput); + } + +/** + * Random Number Generation Algorithm: + * 1.If reseed_counter > reseed_interval, then return an indication that a reseed is required. + * 2.(returned_bits) = Hashgen (requested_number_of_bits, V). + * 3. H = Hash (0x03 || V). Where 0x03 is represented in one byte + * 4. V = (V + H + C + reseed_counter) mod 2 ^seedlen. + * 5. reseed_counter = reseed_counter + 1. + * 6. Return SUCCESS, and update the new values of V, C, and reseed_counter + * for the new_working_state. + * @param aRandomValue on return will contain the generated random numbers.The length of random number + * generated will be equal to the current length of the descriptor(aRandomValue) + * passed as argument to the function call + @panic Panics the kernel with KErrNotReady when the number of requests that can be served has crossed it maximum limit + of KReseedInterval. The panic will indicate that something has badly gone wrong with the Entropy accumulation and + Reseed unit. + * @return KErrNone if everything is fine or KErrNotReady when the system is not ready yet. + */ +TInt DSecureRNG::GenerateRandomNumber(TDes8& aRandomValue) + { + // If requested for random numbers greater than the max limit specified by HASH_DRBG (2^19 bits = 65536 bytes), return error + if(aRandomValue.Length() > KMaxNoOfRequestedBytes) + { + return KErrArgument; + } + + // Secure the random number generation operation through mutex + NKern::ThreadEnterCS(); + Kern::MutexWait(*iSecureRNGMutex); + if(iReseedCounter >= KReseedInterval && iRNGSecure) + { + // If we got reseeded before but haven't been reseeded inside the interval, then something must + // have happened to the entropy collection mechanism (the interval is quite large) - possibly we + // are under attack. There is no way to return to a secure state, so fault the system. + K::Fault(K::ESecureRNGInternalStateNotSecure); + } + iSecureRNGIdle = EFalse; + + // Generate the random numbers + HashGen(aRandomValue); + + const TUint8 KRngConstant = 0x03; + iSha256.Update((TUint8*)&KRngConstant, sizeof(TUint8)); + iSha256.Update(iInternalStateV , KSeedLength); + + // Update the secret value of the Internal State V so that back tracking can be avoided. + // V = (V+C+H+reseed_counter) mod 2 ^seedlength + AddBigNumberToInternalStateV(iInternalStateC, KSeedLength); + AddBigNumberToInternalStateV(iSha256.Final().Ptr(),KSHA256OutLengthInBytes ); + + // Converts iReseedCounter value from little endian to big endian format and stores in tempcounter. + TUint32 tempCounter = ConvertToBigEndian(iReseedCounter); + AddBigNumberToInternalStateV((TUint8*)&tempCounter,sizeof(tempCounter)); + + ++iReseedCounter; + TBool rngSecure = iRNGSecure; + Kern::MutexSignal(*iSecureRNGMutex); + NKern::ThreadLeaveCS(); + + if(rngSecure) + { + return KErrNone; + } + return KErrNotReady; + } + +/** + * Converts the aTempCounter from little endian format to big endian format. This conversion is required + * for performing addition in the function AddBigNumbers(). + * Works fine for 32 bits data only. + * @ return TUint32, big endian format 32 bit value of the iReseedCounter + */ +inline TUint32 DSecureRNG::ConvertToBigEndian(TUint32 aTempCounter) + { + return ((aTempCounter >> 24 & 0x000000ff)| (aTempCounter<< 8 & 0x00ff0000) + |(aTempCounter>>8 & 0x0000ff00) | (aTempCounter << 24 &0xff000000)); + } + +/** + * This function performs addition of an integer(aInteger) passed to the function with iInternalStateV and + * the result is stored in iInternalStateV. The function is required to update the internal state of + * V(iInternalStateV) after each random number generation request. + * @param aInteger this is the input paramenter which is added with iInternalStateV and the result + * is stored in iInternalStateV + * @param aLength length of the aInteger( integer that needs to be added to iInternalStateV) passed to the function + */ +void DSecureRNG::AddBigNumberToInternalStateV(const TUint8* aInteger, TInt aLength) + { + TUint8 sum[2]= {0}; + TInt index = KSeedLength; + while(--index >= 0 && (--aLength >= 0 || sum[1] == 1)) + { + TUint8 integer = (aLength >= 0) ? aInteger[aLength] : (TUint8)0 ; + // sum[0]will hold the value of addition operation and sum[1] will hold carry (if any) + *(TUint16*)&sum = TUint16(iInternalStateV[index] + integer + sum[1]); + iInternalStateV[index] = sum[0]; + } + } + +/** + *Generate the next random number bits to be returned. + * HashGen Algorith: + * 1. m = requested_number_of_bits/ KSHA256OutLengthInBytes. + * 2. data = V. + * 3. W = the Null string. + * 4. For i = 1 to m + * 4.1 wi = Hash (data). + * 4.2 W = W || wi. + * 4.3 data = (data + 1) mod 2^seedlen. + * 5. returned_bits = Leftmost (requested_no_of_bits) bits of W. + * + * Continuous Random number generation test: This is FIPS recommended (FIPS 140-2)test. Definition as per FIPS:- + * 1. If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated + * after power-up, initialization, or reset shall not be used, but shall be saved for comparison with + * the next n-bit block to be generated. Each subsequent generation of an n-bit block shall be compared + * with the previously generated block. The test shall fail if any two compared n-bit blocks are equal. + * 2. If each call to a RNG produces fewer than 16 bits, the first n bits generated after power-up, + * initialization, or reset (for some n > 15) shall not be used, but shall be saved for comparison + * with the next n generated bits. Each subsequent generation of n bits shall be compared with the + * previously generated n bits. The test fails if any two compared n-bit sequences are equal. + * + * @param aRandomBuffer on return, the descriptor will contain the generated random bytes. + * + */ +void DSecureRNG::HashGen(TDes8& aRandomBuffer) + { + TBuf8 data; + // data = V(iInternalStateV) + data.Copy(iInternalStateV, KSeedLength); + + TInt noOfBytesToCopy = aRandomBuffer.Length(); + TInt newLength = noOfBytesToCopy; + //set the length to zero + aRandomBuffer.Zero(); + while(noOfBytesToCopy > 0) + { + newLength = noOfBytesToCopy > KSHA256OutLengthInBytes ? KSHA256OutLengthInBytes: noOfBytesToCopy; + // Append Hashed Data to buffer + aRandomBuffer.Append(HashDataAndCompare(data), newLength); + IncrementData(data); + noOfBytesToCopy = noOfBytesToCopy - KSHA256OutLengthInBytes; + } + } + +/* + * Generates Hash of the aData and compares it with previous generated n(256) random bits to verify for + * Continuous Random number generation test. + * @param aData, the latest copy of iInternalStateV value to be used hash operation + * @return ptr, pointer to the generated hash value using sha256 + */ +inline const TUint8* DSecureRNG::HashDataAndCompare(TDes8& aData) + { + iSha256.Update(aData.Ptr(), aData.Length()); + const TDesC8& ptr = iSha256.Final(); + if(iCompareBuffer.Length()!= 0) + { + // According to FIPS 140-2: if the n-bit random number is same as the previously generated + // n-bit random number then fault the system + __ASSERT_ALWAYS(iCompareBuffer.Compare(ptr)!= 0,K::Fault(K::ESecureRNGOutputsInBadState)); + } + iCompareBuffer.Copy(ptr); + return ptr.Ptr(); + } + +/** + * Calculates (data+1) modulus of 2^440. + * @return aData, on return contains aData value incremented by one + */ +inline void DSecureRNG::IncrementData(TDes8& aData) + { + TInt i = KSeedLength-1; + aData[i] += 1; + while( i > 0 && aData[i] == 0) + { + aData[--i] +=1; + } + } + +/** + * The hash-based derivation function hashes the given input string and + * returns the required no. of bits of hash value on the second parameter. + * Algorithm: + * 1. temp = the Null string. + * 2. len = no_of_bits_to_return / out_len. + * 3. counter = an 8-bit binary value representing the integer "1". + * 4. For i = 1 to len do //Comment : In step 4.1, no_of_bits_to_return is used as a 32-bit string. + * 4.1 temp = temp || Hash (counter || no_of_bits_to_return || input_string). + * 4.2 counter = counter + 1. + * 5. requested_bits = Leftmost (no_of_bits_to_return) of temp. + * 6. Return SUCCESS and requested_bits. + * + * In our case, the no_of_bits_to_return and out_len are constants 440, 256 respectively + * and hence the KLoopLength too becomes constant 2. + * @param, aInputData, holds the input data(state) which needs to be updated + * @param aOutputData, on return will have the updated value of internal State +*/ +void DSecureRNG::HashDf(const TDesC8& aInputData, TUint8* aOutputData) + { + // Seed Length is 440 and SHA256 output block length 256. So required iterations is 2 for 440 bits + const TUint8 KLoopLength = 2; + const TUint32 KNumOfBitsToReturn = KSeedLength * 8; + TInt length = KSHA256OutLengthInBytes; + // Note: The 'length' in memcpy works fine only for curent seed length (440 bits => two iterations) + // In future, if the seed length changes, this too should be modified accoringly. + for (TUint8 counter = 1; counter<= KLoopLength; ++counter) + { + iSha256.Update(&counter, sizeof(TUint8)); + iSha256.Update((TUint8*)&KNumOfBitsToReturn, sizeof(TUint32)); + iSha256.Update(aInputData.Ptr(), aInputData.Length()); + memmove((aOutputData + (counter-1) * KSHA256OutLengthInBytes), iSha256.Final().Ptr(), length); + length = KSeedLength - KSHA256OutLengthInBytes; + } + } + + /** + * This method would generate the new seed with the entropy passed in and update the internal state + * based on the new seed generated. Seed Generation should happen in the following two cases. + * Instantiattion: Internal state updation for the first time with sufficient entropy. + * 1. construct the seed material : seed_material = entropy_input + * 2. seed = Hash_df (seed_material, seedlen). + * 3. V = seed. + * 4. C = Hash_df ((0x00 || V), seedlen). // Precede with a byte of all zeros. + * 5. reseed_counter = 0. + * + * Reseeding: Internal state updation with the sufficient entropy for all instances except first time. + * 1. construct the seed material : seed_material = 0x01 || V || entropy_input + * 2. seed = Hash_df (seed_material, seedlen). + * 3. V = seed. + * 4. C = Hash_df ((0x00 || V), seedlen). // Precede with a byte of all zeros. + * 5. reseed_counter = 0. + * + * In both the cases only the step 1 differs. All other steps are common for both. + * The internal state and other relevant members are protected by the mutex. + * @param aEntropyInput, holds the entropy input values required to update the internal states +*/ +void DSecureRNG::Reseed(const TDesC8& aEntropyInput) + { + const TUint8 KConstOne = 0x01; + TBuf8 seedMaterial; + + // Construct the seed material. + if(iRNGSecure) + { + // After the first seeding (which will set iRNGSecure), seed_material = 0x01 || V || entropy_input + seedMaterial.Append(&KConstOne, sizeof(TUint8)); + seedMaterial.Append(iInternalStateV, KSeedLength); + + // Make the system idle on every reseed (will be reset next time the RNG is used) + iSecureRNGIdle = ETrue; + } + + // The enropy input is used whether it's the first seeding or not. + seedMaterial.Append(aEntropyInput); + + // On the first seeding, include the personalizsation string for the instantiation. + if(!iRNGSecure) + { + // System time in ticks is considered as a personalization string + TInt64 personalizationString = Kern::SystemTimeSecure(); + seedMaterial.Append((TUint8*)&personalizationString, sizeof(TUint)); + } + + // Calculate the seed and update the internal state V + HashDf(seedMaterial, iInternalStateV); + + // Calculate and update the internal state C + seedMaterial.FillZ(1); // Put the 0x00 in the first byte of the buffer + seedMaterial.Append(iInternalStateV, KSeedLength); + HashDf(seedMaterial, iInternalStateC); + + // Reset the reseed counter and other related parameter values as well. + iReseedCounter = 0; + iEntropyPool.Reset(); + // Reset the current estimation. + iEntropyEstimation = 0; + } + +/** + * Controls the Reseed process with the following algorithm. + * 1. Collect the received entropy in the entropy pool like hash object. + * 2. Increment the entropy estimation counter by the received estimation value. + * 3. If the so far collected estimation is higher than the threshold value, + * 3.1. Call Reseed to generate the new seed and update the system internal state + * 3.2. Decide the secure status of the new seed and hence the RNG system + * 3.3. Decide whether the system is idle or not + * 3.4. Reset the entropy pool hash object and the entropy estimation counter. + * +*/ +void DSecureRNG::AddEntropy(const TUint8* aEntropy, TInt aLength, TInt aEstimation) + { + // Get the mutex to update the entropy pool + NKern::ThreadEnterCS(); + Kern::MutexWait(*iEntropyMutex); + + iEntropyPool.Update(aEntropy, aLength); + iEntropyEstimation += aEstimation; + + if (iEntropyEstimation >= iEntropyThreshold) + { + // Get the mutex to update the internal state via Reseed. + Kern::MutexWait(*iSecureRNGMutex); + + // Get the final hash value and pass on to the reseed, which inturn will update the internal state. + Reseed(iEntropyPool.Final()); + + // Set the threshold to 256 for all but the first reseed. For instantiation + // the threshold should be 384 which was set already as part of initialization. + iEntropyThreshold = KReseedThreshold; + + // As the entropy estimation has crossed the threshold, the system becomes secure. + iRNGSecure = ETrue; + + // Send the reseed notification to the hook, if one is installed + if (iReseedHookFn) + iReseedHookFn(iReseedHookArg); + + // Updates are done. So, release the Mutex. + Kern::MutexSignal(*iSecureRNGMutex); + } + + // Updates are done. So, release the Mutex. + Kern::MutexSignal(*iEntropyMutex); + NKern::ThreadLeaveCS(); + } + +// Allow a test driver to set a hook function which will be called on reseed. +void DSecureRNG::SetReseedHook(void (*aReseedHookFn)(TAny*), TAny* aReseedHookArg) + { + NKern::ThreadEnterCS(); + Kern::MutexWait(*iSecureRNGMutex); + iReseedHookFn = aReseedHookFn; + iReseedHookArg = aReseedHookArg; + Kern::MutexSignal(*iSecureRNGMutex); + NKern::ThreadLeaveCS(); + } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/sglobals.cpp --- a/kernel/eka/kernel/sglobals.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/sglobals.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -22,6 +22,8 @@ TLinAddr SuperPageAddress; } +extern void DrainEntropyBuffers(TAny*); + TMachineConfig* K::MachineConfig; RAllocator* K::Allocator; K::SHeapInfo K::HeapInfo; @@ -116,4 +118,18 @@ TMiscNotifierMgr K::TheMiscNotifierMgr; TAny* K::VariantData[31]; +// Array of per CPU entropy buffer status values, each has the number of words used in the bottom 14 bits, +// which may not exceed 2^13 words (32KB or 256Kbit). +// The top 18 bits is the number of bits of entropy with maximum value 2^18 or 256Kbit which matches the buffer size. +TUint32 K::EntropyBufferStatus[KMaxCpus]; + +// Array of per CPU pointers to entropy buffers. +TUint32* K::EntropyBuffer[KMaxCpus]; + +// Temporary buffer to drain per cpu buffers to +TUint32 K::TempEntropyBuffer[KEntropyBufferSizeWords]; + +// DFC to drain entropy buffers +TDfc K::EntropyBufferDfc(DrainEntropyBuffers, NULL, 1); + TDfcQue DShPool::iSharedDfcQue; // DFCQ thread for shareable data buffers growing/shrinking/notifications diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/sha256.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/kernel/sha256.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,464 @@ +/** +* Copyright (c) 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: SHA256 implementation for Random number generation +* kernel\sha256.cpp +* +*/ + +#include "sha256.h" + + +/** + * SHA256 Constants + * + * SHA-256 uses a sequence of sixty-four constant 32-bit words. + * These words represent the first thirty-two bits of the fractional + * parts of the cube roots of the first sixtyfour prime numbers. + * + * FIPS 180-2 Section 4.2.2 + */ +const TUint K[64] = + { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + +inline TUint SHA_Ch(TUint aX, TUint aY, TUint aZ) + { + return ((aX & aY) ^ ((~aX) & aZ)); + } + +inline TUint SHA_Maj(TUint aX, TUint aY, TUint aZ) + { + return ((aX & aY) ^ (aX & aZ) ^ (aY & aZ)); + } + +/** + * SHA Rotate Right Operation: The rotate right (circular right shift) operation + * ROTR^n(x), where x is a w-bit word and n is an integer with 0 <= n < w, + * is defined by ROTR n(x)=(x >> n) || (x << w - n). + */ +inline TUint SHA_ROTR(TUint aBits, TUint aWord) + { + TInt totalBits = sizeof(TUint) << 3; + return ((aWord >> aBits) | (aWord << (totalBits-aBits))); + } + + +/** + * Define the SHA shift, and rotate right macro + * Defined in FIPS 180-2 Section 3.2 + */ +/** + * SHA Right Shift operation: The right shift operation SHR^n(x), + * where x is a w-bit word and n is an integer with 0 <= n < w, + * is defined by SHR^n(x) = x >> n. + */ +inline TUint SHA_SHR(TUint aBits, TUint aWord) + { + return (aWord >> aBits); + } + +/** + * Define the SHA SIGMA and sigma macros + * + * FIPS 180-2 section 4.1.2 + */ +// Equation 4.4 +inline TUint SHA256_SIGMA0(TUint aWord) + { + return (SHA_ROTR(2,aWord) ^ SHA_ROTR(13,aWord) ^ SHA_ROTR(22,aWord)); + } +// Equation 4.5 +inline TUint SHA256_SIGMA1(TUint aWord) + { + return (SHA_ROTR(6,aWord) ^ SHA_ROTR(11,aWord) ^ SHA_ROTR(25,aWord)); + } +// Equation 4.6 +inline TUint SHA256_sigma0(TUint aWord) + { + return (SHA_ROTR(7,aWord) ^ SHA_ROTR(18,aWord) ^ SHA_SHR(3,aWord)); + } +// Equation 4.7 +inline TUint SHA256_sigma1(TUint aWord) + { + return (SHA_ROTR(17,aWord) ^ SHA_ROTR(19,aWord) ^ SHA_SHR(10,aWord)); + } + +// Macros +inline TUint MakeWord(const TUint8* aData) + { + return (aData[0] << 24 | aData[1] << 16 | aData[2] << 8 | aData[3]); + } + +// Constructor +SHA256::SHA256() + { + Reset(); + } + + void SHA256::Reset() + { + /** + * Initial Hash Value + * + * These words were obtained by taking the first thirty-two bits + * of the fractional parts of the square roots of the first eight + * prime numbers. + * + * FIPS 180-2 Section 5.3.2 + */ + iA=0x6a09e667; + iB=0xbb67ae85; + iC=0x3c6ef372; + iD=0xa54ff53a; + iE=0x510e527f; + iF=0x9b05688c; + iG=0x1f83d9ab; + iH=0x5be0cd19; + iNh=0; + iNl=0; + } + +// This assumes a big-endian architecture + void SHA256::Update(const TUint8* aData,TUint aLength) + { + while((aLength / 4) > 0 && (iNl % 4 == 0)) + { + iData[iNl>>2] = MakeWord(aData); + iNl+=4; + aData+=4; + aLength-=4; + if(iNl==KSHA256BlockSize) + { + Block(); + AddLength(KSHA256BlockSize); + } + } + + while(aLength--) + { + if(!(iNl&0x03)) + { + iData[iNl >> 2] = 0; + } + iData[iNl >> 2] |= *aData << ((3 - iNl&0x03) << 3) ; + ++aData; + ++iNl; + if(iNl==KSHA256BlockSize) + { + Block(); + AddLength(KSHA256BlockSize); + } + } + } + +inline void SHA256::AddLength(const TUint aLength) + { + iNh += aLength << 3; + } + + +static inline void CSHA256_16( const TUint aA, + const TUint aB, + const TUint aC, + TUint& aD, + const TUint aE, + const TUint aF, + const TUint aG, + TUint& aH, + TUint aTemp1, + TUint aTemp2, + const TUint aK, + const TUint aWord) + { + aTemp1 = aH + SHA256_SIGMA1(aE) + SHA_Ch(aE,aF,aG) + aK + aWord; + aTemp2 = SHA256_SIGMA0(aA) + SHA_Maj(aA,aB,aC); + aD = aD + aTemp1; + aH = aTemp1 + aTemp2; + } + +static inline void CSHA256_48( const TUint aA, + const TUint aB, + const TUint aC, + TUint& aD, + const TUint aE, + const TUint aF, + const TUint aG, + TUint& aH, + TUint aTemp1, + TUint aTemp2, + const TUint aK, + TUint& aWord0, + const TUint aWord2, + const TUint aWord7, + const TUint aWord15, + const TUint aWord16) + { + aWord0 = SHA256_sigma1(aWord2) + aWord7 + SHA256_sigma0(aWord15) + aWord16; + CSHA256_16(aA, aB, aC, aD, aE, aF, aG, aH, aTemp1, aTemp2, aK, aWord0); + } + +/** + * This function actually calculates the hash. + * Function is defined in FIPS 180-2 section 6.2.2 + * + * This function is the expanded version of the following loop. + * for(TUint i = 0; i < 64; ++i) + * { + * if(i >= 16) + * { + * iData[i] = SHA256_sigma1(iData[i-2]) + iData[i-7] + SHA256_sigma0(iData[i-15]) + iData[i-16]; + * } + * + * temp1 = tempH + SHA256_SIGMA1(tempE) + SHA_Ch(tempE,tempF,tempG) + K[i] + iData[i]; + * temp2 = SHA256_SIGMA0(tempA) + SHA_Maj(tempA,tempB,tempC); + * tempH = tempG; + * tempG = tempF; + * tempF = tempE; + * tempE = tempD + temp1; + * tempD = tempC; + * tempC = tempB; + * tempB = tempA; + * tempA = temp1 + temp2; + * } + */ +void SHA256::Block() + { + TUint tempA=iA; + TUint tempB=iB; + TUint tempC=iC; + TUint tempD=iD; + TUint tempE=iE; + TUint tempF=iF; + TUint tempG=iG; + TUint tempH=iH; + TUint temp1=0; + TUint temp2=0; + + CSHA256_16(tempA,tempB,tempC,tempD,tempE,tempF,tempG,tempH,temp1,temp2,K[0],iData[0]); + CSHA256_16(tempH,tempA,tempB,tempC,tempD,tempE,tempF,tempG,temp1,temp2,K[1],iData[1]); + CSHA256_16(tempG,tempH,tempA,tempB,tempC,tempD,tempE,tempF,temp1,temp2,K[2],iData[2]); + CSHA256_16(tempF,tempG,tempH,tempA,tempB,tempC,tempD,tempE,temp1,temp2,K[3],iData[3]); + CSHA256_16(tempE,tempF,tempG,tempH,tempA,tempB,tempC,tempD,temp1,temp2,K[4],iData[4]); + CSHA256_16(tempD,tempE,tempF,tempG,tempH,tempA,tempB,tempC,temp1,temp2,K[5],iData[5]); + CSHA256_16(tempC,tempD,tempE,tempF,tempG,tempH,tempA,tempB,temp1,temp2,K[6],iData[6]); + CSHA256_16(tempB,tempC,tempD,tempE,tempF,tempG,tempH,tempA,temp1,temp2,K[7],iData[7]); + + CSHA256_16(tempA,tempB,tempC,tempD,tempE,tempF,tempG,tempH,temp1,temp2,K[8],iData[8]); + CSHA256_16(tempH,tempA,tempB,tempC,tempD,tempE,tempF,tempG,temp1,temp2,K[9],iData[9]); + CSHA256_16(tempG,tempH,tempA,tempB,tempC,tempD,tempE,tempF,temp1,temp2,K[10],iData[10]); + CSHA256_16(tempF,tempG,tempH,tempA,tempB,tempC,tempD,tempE,temp1,temp2,K[11],iData[11]); + CSHA256_16(tempE,tempF,tempG,tempH,tempA,tempB,tempC,tempD,temp1,temp2,K[12],iData[12]); + CSHA256_16(tempD,tempE,tempF,tempG,tempH,tempA,tempB,tempC,temp1,temp2,K[13],iData[13]); + CSHA256_16(tempC,tempD,tempE,tempF,tempG,tempH,tempA,tempB,temp1,temp2,K[14],iData[14]); + CSHA256_16(tempB,tempC,tempD,tempE,tempF,tempG,tempH,tempA,temp1,temp2,K[15],iData[15]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[16], iData[16], iData[14], iData[9], iData[1], iData[0]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[17], iData[17], iData[15], iData[10], iData[2], iData[1]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[18], iData[18], iData[16], iData[11], iData[3], iData[2]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[19], iData[19], iData[17], iData[12], iData[4], iData[3]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[20], iData[20], iData[18], iData[13], iData[5], iData[4]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[21], iData[21], iData[19], iData[14], iData[6], iData[5]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[22], iData[22], iData[20], iData[15], iData[7], iData[6]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[23], iData[23], iData[21], iData[16], iData[8], iData[7]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[24], iData[24], iData[22], iData[17], iData[9], iData[8]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[25], iData[25], iData[23], iData[18], iData[10], iData[9]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[26], iData[26], iData[24], iData[19], iData[11], iData[10]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[27], iData[27], iData[25], iData[20], iData[12], iData[11]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[28], iData[28], iData[26], iData[21], iData[13], iData[12]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[29], iData[29], iData[27], iData[22], iData[14], iData[13]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[30], iData[30], iData[28], iData[23], iData[15], iData[14]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[31], iData[31], iData[29], iData[24], iData[16], iData[15]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[32], iData[32], iData[30], iData[25], iData[17], iData[16]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[33], iData[33], iData[31], iData[26], iData[18], iData[17]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[34], iData[34], iData[32], iData[27], iData[19], iData[18]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[35], iData[35], iData[33], iData[28], iData[20], iData[19]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[36], iData[36], iData[34], iData[29], iData[21], iData[20]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[37], iData[37], iData[35], iData[30], iData[22], iData[21]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[38], iData[38], iData[36], iData[31], iData[23], iData[22]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[39], iData[39], iData[37], iData[32], iData[24], iData[23]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[40], iData[40], iData[38], iData[33], iData[25], iData[24]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[41], iData[41], iData[39], iData[34], iData[26], iData[25]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[42], iData[42], iData[40], iData[35], iData[27], iData[26]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[43], iData[43], iData[41], iData[36], iData[28], iData[27]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[44], iData[44], iData[42], iData[37], iData[29], iData[28]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[45], iData[45], iData[43], iData[38], iData[30], iData[29]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[46], iData[46], iData[44], iData[39], iData[31], iData[30]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[47], iData[47], iData[45], iData[40], iData[32], iData[31]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[48], iData[48], iData[46], iData[41], iData[33], iData[32]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[49], iData[49], iData[47], iData[42], iData[34], iData[33]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[50], iData[50], iData[48], iData[43], iData[35], iData[34]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[51], iData[51], iData[49], iData[44], iData[36], iData[35]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[52], iData[52], iData[50], iData[45], iData[37], iData[36]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[53], iData[53], iData[51], iData[46], iData[38], iData[37]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[54], iData[54], iData[52], iData[47], iData[39], iData[38]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[55], iData[55], iData[53], iData[48], iData[40], iData[39]); + + CSHA256_48( tempA, tempB, tempC, tempD, tempE, tempF, tempG, tempH, temp1, temp2, + K[56], iData[56], iData[54], iData[49], iData[41], iData[40]); + CSHA256_48( tempH, tempA, tempB, tempC, tempD, tempE, tempF, tempG, temp1, temp2, + K[57], iData[57], iData[55], iData[50], iData[42], iData[41]); + CSHA256_48( tempG, tempH, tempA, tempB, tempC, tempD, tempE, tempF, temp1, temp2, + K[58], iData[58], iData[56], iData[51], iData[43], iData[42]); + CSHA256_48( tempF, tempG, tempH, tempA, tempB, tempC, tempD, tempE, temp1, temp2, + K[59], iData[59], iData[57], iData[52], iData[44], iData[43]); + CSHA256_48( tempE, tempF, tempG, tempH, tempA, tempB, tempC, tempD, temp1, temp2, + K[60], iData[60], iData[58], iData[53], iData[45], iData[44]); + CSHA256_48( tempD, tempE, tempF, tempG, tempH, tempA, tempB, tempC, temp1, temp2, + K[61], iData[61], iData[59], iData[54], iData[46], iData[45]); + CSHA256_48( tempC, tempD, tempE, tempF, tempG, tempH, tempA, tempB, temp1, temp2, + K[62], iData[62], iData[60], iData[55], iData[47], iData[46]); + CSHA256_48( tempB, tempC, tempD, tempE, tempF, tempG, tempH, tempA, temp1, temp2, + K[63], iData[63], iData[61], iData[56], iData[48], iData[47]); + + iA+=tempA; + iB+=tempB; + iC+=tempC; + iD+=tempD; + iE+=tempE; + iF+=tempF; + iG+=tempG; + iH+=tempH; + + iNl=0; + } + +/** + * According to the standard, the message must be padded to an + * even 512 bits. The first padding bit must be a '1'. The last + * 64 bits represent the length of the original message. All bits + * in between should be 0. This helper function will pad the + * message according to those rules by filling the iData array + * accordingly. + */ +void SHA256::PadMessage() + { + const TUint padByte = 0x80; + + if(!(iNl&0x03)) + { + iData[iNl >> 2] = 0; + } + iData[iNl >> 2] |= padByte << ((3 - iNl&0x03) << 3) ; + + if (iNl >= (KSHA256BlockSize - 2*sizeof(TUint))) + { + if (iNl < (KSHA256BlockSize - sizeof(TUint))) + iData[(KSHA256BlockSize >> 2) - 1]=0; + Block(); + memset(iData , 0 ,KSHA256BlockSize*sizeof(TUint)); + } + else + { + const TUint offset=(iNl+4)>>2; //+4 to account for the word added in the + //switch statement above + memset((iData+offset), 0, ((KSHA256BlockSize - offset*sizeof(TUint))*sizeof(TUint))); + } + + //Length in bits + TUint64 msgLength = iNh; + + iData[(KSHA256BlockSize >> 2) - 2] = static_cast((msgLength) >> 32); + iData[(KSHA256BlockSize >> 2) - 1] = static_cast((msgLength & 0xFFFFFFFF)); + } + + +inline void SHA256::CopyWordToHash(TUint aVal, TInt aIndex) + { + TUint value = MakeWord(reinterpret_cast(&aVal)); + memmove(const_cast(iHash.Ptr())+ (4*aIndex), &value, sizeof(aVal)); + } + + + const TDesC8& SHA256::Final() + { + AddLength(iNl); + PadMessage(); + Block(); + // + // Generate hash value into iHash + // + CopyWordToHash(iA,0); + CopyWordToHash(iB,1); + CopyWordToHash(iC,2); + CopyWordToHash(iD,3); + CopyWordToHash(iE,4); + CopyWordToHash(iF,5); + CopyWordToHash(iG,6); + CopyWordToHash(iH,7); + Reset(); + return iHash; + } + + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/sinit.cpp --- a/kernel/eka/kernel/sinit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/sinit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -21,6 +21,7 @@ #include #include #include "platform.h" +#include "securerng.h" #ifdef __VC32__ #pragma setlocale("english") @@ -46,6 +47,7 @@ TInt SupervisorThread(TAny*); TInt DebuggerInit(); +extern TInt InitialiseEntropyBuffers(); extern const SNThreadHandlers EpocThreadHandlers; @@ -392,6 +394,7 @@ K::Fault(K::EInit3Failed); P::StartExtensions(); + M::Init4(); K::StartKernelServer(); return 0; } @@ -442,6 +445,14 @@ r=K::StartTickQueue(); if (r!=KErrNone) return r; + + // Initilize the Secure RNG. + SecureRNG = new DSecureRNG; + + // Initialise entropy buffers for secure RNG + r=InitialiseEntropyBuffers(); + if (r!=KErrNone) + return r; // Third phase initialisation of ASIC/Variant // This enables the system tick and millisecond timer @@ -450,9 +461,6 @@ // Mark the super page signature valid P::SetSuperPageSignature(); - // Initialise the random pool - K::Randomize(); - return KErrNone; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/srandombuff.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/kernel/srandombuff.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,204 @@ +/** +* Copyright (c) 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: +* eka\kernel\srandombuff.cpp +* +*/ + +#include +#include +#include "kernel/securerng.h" + +const TInt KWordIndexBitMask = 0x1FFF; // bottom 13 bits holds buffer word index +const TInt KEntropyCountBitShift = 14; // top 18 bits holds entropy count +const TUint KEntropyBufferThresholdWords = KEntropyBufferSizeWords * 3/4; + +/** + Adds a single bit to the random pool used to generate random numbers. + + @deprecated use Kern::RandomSalt(TUint32 aEntropyData, TUint aBitsOfEntropy) or Kern::RandomSalt(TUint64 aEntropyData, TUint aBitsOfEntropy) instead + + @param aBitOfSalt The least significant bit of this value is added to the random pool. + + @pre Can be used in a device driver. +*/ +EXPORT_C void Kern::RandomSalt(TUint32 aBitOfSalt) + { + // Check if RNG needs more entropy. + if (SecureRNG->SecureRNGIdle()) + return; + + Kern::RandomSalt(aBitOfSalt, 1); + } + + +/** + Adds 32 bits of data, using the entropy estimate provided, to the random pool used to generate random numbers. + + @param aEntropyData The 32 bits of data to be added to the random pool. + @param aBitsOfEntropy An estimate of the number of bits of entropy contained in the 32 bits of data. + + @pre aBitsOfEntropy must be >=0 and <=32. + @pre Can be used in a device driver. +*/ +EXPORT_C void Kern::RandomSalt(TUint32 aEntropyData, TUint aBitsOfEntropy) + { + // Check if RNG needs more entropy. + if (SecureRNG->SecureRNGIdle()) + return; + + __ASSERT_ALWAYS((TUint)aBitsOfEntropy <= 32, K::PanicKernExec(EEntropyEstimateOutOfRange)); + + TUint32 addcounts = (aBitsOfEntropy << KEntropyCountBitShift) + 1; // top 18 bits holds entropy count, plus 1 to increment buffer word index + + TInt irq = NKern::DisableAllInterrupts(); + + TInt currentcpu = NKern::CurrentCpu(); + + TUint32 currentstatus = __e32_atomic_load_acq32(&K::EntropyBufferStatus[currentcpu]); + TUint32 nextword = currentstatus & KWordIndexBitMask; // bottom 13 bits holds buffer word index + + if(nextword < KEntropyBufferSizeWords) + { + K::EntropyBuffer[currentcpu][nextword] = aEntropyData; + __e32_atomic_add_ord32(&K::EntropyBufferStatus[currentcpu], addcounts); + } + + NKern::RestoreInterrupts(irq); + + TUint32 entropycount = (currentstatus + addcounts) >> KEntropyCountBitShift; // top 18 bits holds entropy count + if((nextword < KEntropyBufferSizeWords) && (entropycount >= KReseedThreshold || nextword > KEntropyBufferThresholdWords)) + { + if (NKern::CurrentContext() == NKern::EInterrupt) + K::EntropyBufferDfc.Add(); + else + K::EntropyBufferDfc.Enque(); + } + } + + +/** + Adds 64 bits of data, using the entropy estimate provided, to the random pool used to generate random numbers. + + @param aEntropyData The 64 bits of data to be added to the random pool. + @param aBitsOfEntropy An estimate of the number of bits of entropy contained in the 32 bits of data. + + @pre aBitsOfEntropy must be >=0 and <=64. + @pre Can be used in a device driver. +*/ +EXPORT_C void Kern::RandomSalt(TUint64 aEntropyData, TUint aBitsOfEntropy) + { + // Check if RNG needs more entropy. + if (SecureRNG->SecureRNGIdle()) + return; + + __ASSERT_ALWAYS((TUint)aBitsOfEntropy <= 64, K::PanicKernExec(EEntropyEstimateOutOfRange)); + + TUint32 addcounts = (aBitsOfEntropy << KEntropyCountBitShift) + 2; // top 18 bits holds entropy count, plus 2 to increment buffer word index + + TInt irq = NKern::DisableAllInterrupts(); + + TInt currentcpu = NKern::CurrentCpu(); + + TUint32 currentstatus = __e32_atomic_load_acq32(&K::EntropyBufferStatus[currentcpu]); + TUint32 nextword = currentstatus & KWordIndexBitMask; // bottom 13 bits holds buffer word index + + if((nextword + 1) < KEntropyBufferSizeWords) + { + K::EntropyBuffer[currentcpu][nextword] = I64LOW(aEntropyData); + K::EntropyBuffer[currentcpu][nextword+1] = I64HIGH(aEntropyData); + __e32_atomic_add_ord32(&K::EntropyBufferStatus[currentcpu], addcounts); + } + + NKern::RestoreInterrupts(irq); + + TUint32 entropycount = (currentstatus + addcounts) >> KEntropyCountBitShift; // top 18 bits holds entropy count + if((nextword < KEntropyBufferSizeWords) && (entropycount >= KReseedThreshold || nextword > KEntropyBufferThresholdWords)) + { + if (NKern::CurrentContext() == NKern::EInterrupt) + K::EntropyBufferDfc.Add(); + else + K::EntropyBufferDfc.Enque(); + } + } + + +#if defined(__EPOC32__) + +EXPORT_C void Interrupt::AddTimingEntropy() + { + // This function should only be called from Interrupt context otherwise timing may be predictable. + CHECK_PRECONDITIONS(MASK_NOT_THREAD|MASK_NOT_IDFC, "Interrupt::AddTimingEntropy()"); + + // Check if RNG needs more entropy. + if (SecureRNG->SecureRNGIdle()) + return; + + TUint32 timestamp = NKern::FastCounter(); + + Kern::RandomSalt(timestamp, 1); + } + +#endif + +extern void DrainEntropyBuffers(TAny*) + { + TUint32 wordsavailable = 0; + TUint32 wordscopied; + TUint32 currentstatus; + TBool result = 0; + + for(TInt cpu = (NKern::NumberOfCpus() - 1); cpu >= 0; --cpu) + { + wordscopied = 0; + currentstatus = __e32_atomic_load_acq32(&K::EntropyBufferStatus[cpu]); + + // if this CPU's buffer is empty then skip processing + if(currentstatus == 0) continue; + + do + { + wordsavailable = currentstatus & KWordIndexBitMask; + + memcpy(&K::TempEntropyBuffer[wordscopied], &K::EntropyBuffer[cpu][wordscopied], (wordsavailable - wordscopied)*4); + + wordscopied = wordsavailable; + + result = __e32_atomic_cas_ord32(&K::EntropyBufferStatus[cpu], ¤tstatus, 0); + } + while(!result); + + SecureRNG->AddEntropy((TUint8*)&K::TempEntropyBuffer[0], wordscopied*4, currentstatus >> KEntropyCountBitShift); + } + } + + +extern TInt InitialiseEntropyBuffers() + { + TInt numcpus = NKern::NumberOfCpus(); + + // Allocate space for all cpu buffers and store pointer to beginning as CPU 0 buffer. + K::EntropyBuffer[0] = (TUint32*)Kern::Alloc(KEntropyBufferSizeWords * numcpus * 4); + + // Initialise pointers for remaining cpus + for(TInt cpu = 1; cpu < numcpus; ++cpu) + { + K::EntropyBuffer[cpu] = K::EntropyBuffer[0] + (cpu * KEntropyBufferSizeWords); + } + + // Initialise DFC + K::EntropyBufferDfc.SetDfcQ(K::SvMsgQ); + + return KErrNone; + } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/kernel/stest.cpp --- a/kernel/eka/kernel/stest.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/kernel/stest.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -17,6 +17,7 @@ #include #include "kern_test.h" +#include "securerng.h" #ifdef _DEBUG class TTestCallback: public TUserModeCallback @@ -60,9 +61,9 @@ TInt r = KErrNotSupported; (void)aFunc; (void)a1; (void)a2; (void)a3; -#ifdef _DEBUG switch(aFunc) { +#ifdef _DEBUG case EUserModeCallbackSleep: { // a1 is a DThread*. We add a user mode callback to that thread @@ -85,8 +86,18 @@ NKern::ThreadLeaveCS(); break; } +#endif + case ERNGReseedHook: + { + // a1 is a function which wants to be called with arg a2 when the RNG is reseeded. + // Used to test if reseeds are sufficiently frequent. + SecureRNG->SetReseedHook((void(*)(TAny*))a1, a2); + break; + } + default: + // To stop compiler warnings about unhandled enum cases in release builds + break; } -#endif return r; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/emul/win32/minit.cpp --- a/kernel/eka/memmodel/emul/win32/minit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/emul/win32/minit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -67,6 +67,11 @@ __KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("M::Init3")); } +void M::Init4() + { + // Fourth phase MMU initialisation - Not required on this memory model. + } + // kernel heap construction void P::KernelInfo(TProcessCreateInfo& aInfo, TAny*& aStack, TAny*& aHeap) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/direct/minit.cpp --- a/kernel/eka/memmodel/epoc/direct/minit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/direct/minit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -84,6 +84,11 @@ // Third phase MMU initialisation } +void M::Init4() + { + // Fourth phase MMU initialisation - Not required on this memory model. + } + TInt M::InitSvHeapChunk(DChunk* aChunk, TInt aSize) { DMemModelChunk* pC=(DMemModelChunk*)aChunk; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/minit.cpp --- a/kernel/eka/memmodel/epoc/flexible/minit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/minit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -18,6 +18,9 @@ #include "mmboot.h" #include "cache_maintenance.h" +#include "mmu/mmu.h" +#include "mmu/mpager.h" + extern void DoProcessSwitch(); @@ -52,6 +55,12 @@ MM::Init3(); } +void M::Init4() + { + // Fourth phase MMU initialisation + ThePager.InitCache(); + } + TInt M::InitSvHeapChunk(DChunk* aChunk, TInt aSize) { diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/arm/xmmu.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/arm/xmmu.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/arm/xmmu.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -503,8 +503,54 @@ case EMemAttNormalCached: texcb = KArmV6MemAttWBWAWBWA; break; - default: - __NK_ASSERT_ALWAYS(0); // undefined memory type + case EMemAttKernelInternal4: + case EMemAttPlatformSpecific5: + case EMemAttPlatformSpecific6: + case EMemAttPlatformSpecific7: + { + TUint32 cachingAttr = InternalCache::TypeToCachingAttributes((TMemoryType)(attr&EMemoryAttributeTypeMask)); + switch (cachingAttr) + { + case EMapAttrFullyBlocking: + texcb = KArmV6MemAttSO; + break; + case EMapAttrBufferedNC: + texcb = KArmV6MemAttSD; + break; + default: + { + //attr describes normal mapping + //set texcb to b1BBAA where AA is internal and BB is external caching + // TYPE AA/BB + // uncached 0 + // WBWA 1 + // WTRA 2 + // WBRA 3 + texcb = 0x10; + switch (cachingAttr&EMapAttrL1CacheMask) + { + case EMapAttrL1Uncached: break; + #if defined(__CPU_ARM1136_ERRATUM_399234_FIXED) + case EMapAttrCachedWTRA: texcb |= 2;break; // It is OK to use WT memory + #else + case EMapAttrCachedWTRA:;break; // Erratum not fixed. Use uncached memory instead + #endif + case EMapAttrCachedWBRA: texcb |= 3; break; + default: texcb |= 1;//fully cached (WBWA) + } + switch (cachingAttr&EMapAttrL2CacheMask) + { + case EMapAttrL2Uncached: break; + case EMapAttrL2CachedWTRA: texcb |= 8;break; + case EMapAttrL2CachedWBRA: texcb |= 0xc; break; + default: texcb |= 4;//fully cached (WBWA) + } + } + } + } + break; + default: + __NK_ASSERT_ALWAYS(0); // undefined memory type texcb = KArmV6MemAttSO; break; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -905,9 +905,6 @@ // initialise address spaces... DAddressSpace::Init2(); - // init pager... - ThePager.Init2(); - TheMmu.Init2Final(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/mmapping.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mmapping.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mmapping.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1435,7 +1435,7 @@ { TRACE(("DVirtualPinMapping::New(0x%x)",aMaxCount)); DVirtualPinMapping* self = new DVirtualPinMapping; - if(aMaxCount) + if(self && aMaxCount) { // pages have been reserved for our use. diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/mobject.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mobject.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mobject.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -506,9 +506,17 @@ if(self) { new (self) DPageTables(aMemory,numPts,aPteType); + // Add this page tables object to the memory object before we update any + // page table entries. To ensure that if any of aMemory's pages with + // corresponding page table entries in self are moved during Construct(), + // DCoarseMemory::RemapPage() will be able to find the page table entries + // to update via iPageTables. + __NK_ASSERT_DEBUG(!aMemory->iPageTables[aPteType]); + aMemory->iPageTables[aPteType] = self; TInt r = self->Construct(); if(r!=KErrNone) { + aMemory->iPageTables[aPteType] = 0; self->Close(); self = 0; } @@ -1689,11 +1697,6 @@ { // allocate a new one if required... tables = DPageTables::New(this, iSizeInPages, aPteType); - if (tables) - { - __NK_ASSERT_DEBUG(!iPageTables[aPteType]); - iPageTables[aPteType] = tables; - } } return tables; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -50,14 +50,26 @@ DPager::DPager() : iMinimumPageCount(0), iMaximumPageCount(0), iYoungOldRatio(0), - iYoungCount(0),iOldCount(0),iNumberOfFreePages(0) + iYoungCount(0),iOldCount(0), +#ifdef _USE_OLDEST_LISTS + iOldestCleanCount(0), +#endif + iNumberOfFreePages(0), iReservePageCount(0), iMinimumPageLimit(0) { } -void DPager::Init2() +void DPager::InitCache() { - TRACEB(("DPager::Init2()")); + // + // This routine doesn't acquire any mutexes because it should be called before the system + // is fully up and running. I.e. called before another thread can preempt this. + // + TRACEB(("DPager::InitCache()")); + // If any pages have been reserved then they will have already been allocated and + // therefore should be counted as part of iMinimumPageCount. + __NK_ASSERT_DEBUG(iReservePageCount == iMinimumPageCount); + __NK_ASSERT_DEBUG(!CacheInitialised()); #if defined(__CPU_ARM) @@ -104,85 +116,92 @@ __NK_ASSERT_DEBUG(KMinOldPages<=iAbsoluteMinPageCount/2); - // initialise live list... - TUint minimumPageCount = 0; - TUint maximumPageCount = 0; - + // Read any paging config data. SDemandPagingConfig config = TheRomHeader().iDemandPagingConfig; - iMinimumPageCount = KDefaultMinPages; - if(minimumPageCount) - iMinimumPageCount = minimumPageCount; - if(config.iMinPages) - iMinimumPageCount = config.iMinPages; - if(iMinimumPageCount KAbsoluteMaxPageCount) - iMaximumPageCount = KAbsoluteMaxPageCount; - iInitMaximumPageCount = iMaximumPageCount; - + // Set the list ratios... iYoungOldRatio = KDefaultYoungOldRatio; if(config.iYoungOldRatio) iYoungOldRatio = config.iYoungOldRatio; - TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages; - if(iYoungOldRatio>ratioLimit) - iYoungOldRatio = ratioLimit; - #ifdef _USE_OLDEST_LISTS iOldOldestRatio = KDefaultOldOldestRatio; if(config.iSpare[2]) iOldOldestRatio = config.iSpare[2]; #endif - iMinimumPageLimit = (iMinYoungPages * (1 + iYoungOldRatio)) / iYoungOldRatio; - if(iMinimumPageLimit iMinimumPageCount) + iMinimumPageCount = iMinimumPageLimit + iReservePageCount; + + iInitMinimumPageCount = iMinimumPageCount; + + // Set the maximum page counts... + iMaximumPageCount = KMaxTInt; + if(config.iMaxPages) + iMaximumPageCount = config.iMaxPages; + if (iMaximumPageCount > KAbsoluteMaxPageCount) + iMaximumPageCount = KAbsoluteMaxPageCount; + iInitMaximumPageCount = iMaximumPageCount; + + + TRACEB(("DPager::InitCache() live list min=%d max=%d ratio=%d",iMinimumPageCount,iMaximumPageCount,iYoungOldRatio)); + + // Verify the page counts are valid. + __NK_ASSERT_ALWAYS(iMaximumPageCount >= iMinimumPageCount); TUint minOldAndOldest = iMinimumPageCount / (1 + iYoungOldRatio); - if(minOldAndOldest < KMinOldPages) - __NK_ASSERT_ALWAYS(0); - if (iMinimumPageCount < minOldAndOldest) - __NK_ASSERT_ALWAYS(0); + __NK_ASSERT_ALWAYS(minOldAndOldest >= KMinOldPages); + __NK_ASSERT_ALWAYS(iMinimumPageCount >= minOldAndOldest); + + // Need at least iMinYoungPages pages mapped to execute worst case CPU instruction TUint minYoung = iMinimumPageCount - minOldAndOldest; - if(minYoung < iMinYoungPages) - __NK_ASSERT_ALWAYS(0); // Need at least iMinYoungPages pages mapped to execute worst case CPU instruction + __NK_ASSERT_ALWAYS(minYoung >= iMinYoungPages); + + // Verify that the young old ratio can be met even when there is only the + // minimum number of old pages. + TInt ratioLimit = (iMinimumPageCount-KMinOldPages)/KMinOldPages; + __NK_ASSERT_ALWAYS(iYoungOldRatio <= ratioLimit); + #ifdef _USE_OLDEST_LISTS // There should always be enough old pages to allow the oldest lists ratio. TUint oldestCount = minOldAndOldest / (1 + iOldOldestRatio); - if (!oldestCount) - __NK_ASSERT_ALWAYS(0); + __NK_ASSERT_ALWAYS(oldestCount); #endif + iNumberOfFreePages = 0; iNumberOfDirtyPages = 0; - // Allocate RAM pages and put them all on the old list + // Allocate RAM pages and put them all on the old list. + // Reserved pages have already been allocated and already placed on the + // old list so don't allocate them again. RamAllocLock::Lock(); iYoungCount = 0; +#ifdef _USE_OLDEST_LISTS iOldCount = 0; -#ifdef _USE_OLDEST_LISTS - iOldestCleanCount = 0; iOldestDirtyCount = 0; + __NK_ASSERT_DEBUG(iOldestCleanCount == iReservePageCount); +#else + __NK_ASSERT_DEBUG(iOldCount == iReservePageCount); #endif Mmu& m = TheMmu; - for(TUint i=0; iiName,aDevice->iType)); + __NK_ASSERT_DEBUG(!ThePager.CacheInitialised()); __NK_ASSERT_ALWAYS(aDevice->iReadUnitShift <= KPageShift); TInt r = KErrNotSupported; // Will return this if unsupported device type is installed diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/flexible/mmu/mpager.h --- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h Sat Feb 20 00:10:51 2010 +0200 @@ -29,9 +29,14 @@ { public: DPager(); - void Init2(); + void InitCache(); void Init3(); + FORCE_INLINE TBool CacheInitialised() + { + return iYoungOldRatio && iMinimumPageLimit; + } + FORCE_INLINE TUint NumberOfFreePages() { return iNumberOfFreePages; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/moving/minit.cpp --- a/kernel/eka/memmodel/epoc/moving/minit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/moving/minit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -54,6 +54,11 @@ m.Init3(); } +void M::Init4() + { + // Fourth phase MMU initialisation - Not required on this memory model. + } + TInt M::InitSvHeapChunk(DChunk* aChunk, TInt aSize) { TInt r; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/multiple/minit.cpp --- a/kernel/eka/memmodel/epoc/multiple/minit.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/multiple/minit.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -49,6 +49,11 @@ m.Init3(); } +void M::Init4() + { + // Fourth phase MMU initialisation - Not required on this memory model. + } + TInt M::InitSvHeapChunk(DChunk* aChunk, TInt aSize) { TInt r; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/memmodel/epoc/putils.cpp --- a/kernel/eka/memmodel/epoc/putils.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/memmodel/epoc/putils.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -428,11 +428,6 @@ static const TUint32 KMapAttrType2 = 0x80000000; static const TUint32 KMapAttrTypeShift = 26; -#if defined(__CPU_MEMORY_TYPE_REMAPPING) -extern TUint32 PrimaryRegionRemapRegister(); -extern TUint32 NormalMemoryRemapRegister(); -#endif - EXPORT_C TMappingAttributes2::TMappingAttributes2(TMemoryType aType, TBool aUserAccess, TBool aWritable, diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/release.txt --- a/kernel/eka/release.txt Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/release.txt Sat Feb 20 00:10:51 2010 +0200 @@ -1,3 +1,120 @@ +Version 2.00.2075 +================= +(Made by vfebvre 26/01/2010) + +1. josezhou + 1. DEF143803 COPY of DEF143562:No error note about connected USB HUB shown + 2. DEF143802 copied open for submission:EDHO-7Y3AAD, USB connection: + 3. DEF143804 COPY of DEF143568:USB using an obsoleted API to allocate endpoint resource + 4. DEF143799 COPY of DEF142812: SMP-Panic in the TDfcQue::ThreadFunction when USB channel is + 5. DEF143800 COPY of DEF142888: SMP-t_usbdi test case 1231 failed + +2. ange + 1. PDEF143797 Precondition is not met when USB OTG driver use Kernel API + +3. vfebvre + 1. MINOR_CHANGE Fixed test code for File Header Relocation + + +Version 2.00.2074 +================= +(Made by vfebvre 25/01/2010) + +1. djkovace + 1. DEF143683 Fix PL310 erratum 727915 + +2. dogunjum + 1. DEF137221 NE1 PCI driver not confirmed SMPSAFE automatic test case missing + +3. vfebvre + 1. DEF143067 BTracex_ldd causing missing file warning in CTS77 image creation - TSW Defect + + +Version 2.00.2073 +================= +(Made by vfebvre 25/01/2010) + +1. mmoate + 1. MILESTONE: SymTB9.2, GT0660, MS3.8, DS.1456 + REQ427:125 Cryptographically-Strong Random Number Generator [PREQ211] + + +Version 2.00.2072 +================= +(Made by vfebvre 25/01/2010) + +1. vfebvre + 1. MINOR_CHANGE Update required to base_e32.mrp for Header Relocation + + +Version 2.00.2071 +================= +(Made by vfebvre 21/01/2010) + +1. ryharkin + 1. PDEF143852 - TConsoleKey missing iPointerNumber + The text window server class TConsoleKey is missing the iPointerNumber member value + + +Version 2.00.2070 +================= +(Made by vfebvre 18/01/2010) + +1. shamaden + 1. DEF143440 t_heap fails when KHeapMinCellSize = 16 + +2. necliffo + 1. DEF143882: SALM-7ZQN53 WDP: EMMC drive not mountable as Mass Storage + +3. gcochran + 1. DEF143458: E32 T_CODEPAGING test is not support large page cache (TB9.2) TSW: EYGL-7T38TL + +4. vfebvre + 1. DEF142990 Change to Make Files - Causing OS Base Build Failure + + +Version 2.00.2069 +================= +(Made by vfebvre 15/01/2010) + +1. martai + 1. DEF143580: t_fuzzldr crashes/hangs on FMM and Datapaged ROMs + 2. DEF143441: FMM: Minimise size of live list when demand paging disabled + +2. tommarti + 1. Fix for DEF140936: T_WDPSTRESS fails on NaviEngine SMPPAGE/SMPKERNEL + + +Version 2.00.2068 +================= +(Made by vfebvre 15/01/2010) + +1. djkovace + 1. PDEF143736 OOM defect in DVirtualPinMapping::New + 2. PDEF143812 Support platform specific mappings on 1136 + +2. necliffo + 1. DEF143340 JPLS-7XXEAC: eMMC initialisation fails with Samsung 32GB + 2. DEF143593 WDP: Phone does not boot if SWAP drive is corrupted + +3. martai + 1. DEF142714: Frequent T_RAMDEFRAG failures observed on the H4 + +4. vfebvre + 1. PDEF143659 Bootstrap.flm and related bld.inf changes not submitted to the MCL + +5. marisood + 1. DEF143212: Missing M&FS files from Symbian Foundation due to IP classifications + + +Version 2.00.2067 +================= +(Made by vfebvre 12/01/2010) + +1. cnotton + 1. MINOR_CHANGE Fixed some smaller compile issues with split and relocation header changes. + + Version 2.00.2066 ================= (Made by vfebvre 11/01/2010) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/rombuild/ost.iby --- a/kernel/eka/rombuild/ost.iby Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/rombuild/ost.iby Sat Feb 20 00:10:51 2010 +0200 @@ -17,7 +17,6 @@ #ifndef OST_IBY #define OST_IBY -#include //Put kernel side DLLs in the core image on NAND configurations //since that's where the majority of the client code will also be. diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kernel/eka/rombuild/utrace.iby --- a/kernel/eka/rombuild/utrace.iby Tue Feb 02 01:24:03 2010 +0200 +++ b/kernel/eka/rombuild/utrace.iby Sat Feb 20 00:10:51 2010 +0200 @@ -17,7 +17,6 @@ #ifndef UTRACE_IBY #define UTRACE_IBY -#include //Put kernel side DLLs in the core image on NAND configurations //since that's where the majority of the client code will also be. diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/defrag/t_ramdefrag.cpp --- a/kerneltest/e32test/defrag/t_ramdefrag.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/defrag/t_ramdefrag.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -575,6 +575,10 @@ UpdateRamInfo(); gEndRam = gFreeRam; TESTDEBUG(test.Printf(_L("End RAM Free = 0x%x, End RAM Used = 0x%x\n"), gEndRam, gRamUsed)); + + // Ensure any asynchronous clean up operations complete before we move on + // to the next test. + UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); CheckRamDifference(); test.Printf(_L(" \n")); } @@ -1753,6 +1757,12 @@ //! 7. Allocate discardable pages by loading pages that are demand paged. //! Check which zone the memory has been allocated to by checking the number of //! discardable pages before and after the allocation has taken place. +//! 8. Allocate a contiguous fixed page into a zone which is full of movable or discardable pages. +//! 9. Allocate a large 1MB aligned chunk with as few pages as possible availiable for page tables, +//! then clear to every page in the chunk. This is attempting to ensure that the chunk pages +//! that have page tables associated to them are remapped correctly if the chunk pages have to be +//! moved so page table pages to map other pages in the chunk are allocated in the most preferable +//! ram zones. //! //! @SYMTestExpectedResults //! 1. The memory has been allocated to the most preferred zone with the least amount of @@ -1765,6 +1775,9 @@ //! 6. Extra page is placed in the next preferable to the "best"zone //! 7. Memory is allocated to the most preferred zone with the least amount of //! space accounting for the zone threshold for discardable pages. +//! 8. The fixed page is allocated as it has moved or discarded a page. +//! 9. The chunk is cleared succesfully. +//! //--------------------------------------------------------------------------------------------------------------------- TInt TestAllocStrategies() { @@ -2469,6 +2482,37 @@ skipTest8: TestEnd(); + test.Next(_L("Test9: Allocate a large 1MB aligned chunk and touch all its pages")); + TestStart(); + gChunkArray1 = new RChunk; + gChunkArraySize1 = 1; + + GetAllPageInfo(); + const TUint KChunkBytes = 0x100000; + const TUint KChunkMask = KChunkBytes - 1; + TUint freeBytes = gTotalPageCount.iFreePages << gPageShift; + TUint chunkSize = freeBytes & ~KChunkMask; + // Fill as much memory as possible with fixed pages while still allowing the movable allocation to succeed. + // This should help force the page table allocation for the chunk to need to move pages. + TUint fixedSize = freeBytes - chunkSize; + r = KErrNoMemory; + while (r != KErrNone && fixedSize) + { + Ldd.FreeAllFixedPages(); + fixedSize -= gPageSize; + test.Printf(_L("fixedSize 0x%x\n"), fixedSize); + r = Ldd.AllocateFixed(fixedSize >> gPageShift); + if (r != KErrNone) + break; + r = AllocMovable(gChunkArray1, gChunkArraySize1, gChunkArraySize1, chunkSize); + } + if (r == KErrNone) + { + // Touch every page in the chunk. + memclr(gChunkArray1->Base(), chunkSize); + } + TestEnd(); // This will free any chunk and fixed pages. + test.End(); return KErrNone; } @@ -3805,6 +3849,8 @@ Ldd.FreeAllFixedPages(); TestEnd(); + PrintPageInfo(); + test.Next(_L("Test7: Defrag memory filled with discardable pages when the min cache size is reached\n")); TestStart(); if (gPagedRom) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/device/t_usb.h --- a/kerneltest/e32test/device/t_usb.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/device/t_usb.h Sat Feb 20 00:10:51 2010 +0200 @@ -86,10 +86,13 @@ TBool iBufferSizeChosen; TBool iBandwidthPriorityChosen; TBool iDMAChosen; + TBool iAllocateDma; TBool iDoubleBufferingChosen; + TBool iAllocateDoubleBuffering; TUint32 iBandwidthPriority; TBool iSoftwareConnect; TBool iHighSpeed; + TBool iResourceAllocationV2; TBool iOtg; TBool iVerbose; }; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/device/t_usbapi.cpp --- a/kerneltest/e32test/device/t_usbapi.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/device/t_usbapi.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -60,6 +60,7 @@ static RUsbOtgDriver gOTG; static TBool gSupportsOtg; static TBool gSupportsHighSpeed; +static TBool gSupportResouceAllocationV2; static TBool gUsingHighSpeed; static TBool gSoak; static TChar gKeychar = 'a'; @@ -282,7 +283,7 @@ } -static void TestResourceAllocation() +static void TestResourceAllocationV1() { test.Start(_L("Test Endpoint Resource Allocation")); @@ -347,7 +348,8 @@ // Global variable - we'll need this value later gSupportsHighSpeed = d_caps().iHighSpeed; - + gSupportResouceAllocationV2 = (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2); + test.Printf(_L("### USB device capabilities:\n")); test.Printf(_L("Number of endpoints: %d\n"), n); test.Printf(_L("Supports Software-Connect: %s\n"), @@ -364,8 +366,7 @@ (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? _S("yes") : _S("no")); test.Printf(_L("Supports endpoint resource alloc scheme V2: %s\n"), - (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ? - _S("yes") : _S("no")); + gSupportResouceAllocationV2 ? _S("yes") : _S("no")); test(n >= 2); test.Printf(_L("(Device has sufficient endpoints.)\n")); @@ -446,7 +447,10 @@ // Some UDCs won't allow endpoint resource manipulation once the hardware has been // configured and turned on. So we do it here & now: - TestResourceAllocation(); + if (!gSupportResouceAllocationV2) + { + TestResourceAllocationV1(); + } // On the other hand, since some UDCs won't let us test many features which require // register access until the USB hardware is powered up (and because it might start @@ -504,6 +508,13 @@ r = gPort.ReleaseInterface(0); test(r == KErrNone); + if (gSupportResouceAllocationV2) + { + test.Next(_L("setting resource allocation info on endpoint 1 with resource allocation scheme v2")); + ifc().iEndpointData[0].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; + ifc().iEndpointData[0].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DoubleBuffering; + } + test.Next(_L("Setting interface")); r = gPort.SetInterface(0, ifc); test(r == KErrNone); @@ -536,6 +547,18 @@ // Suspend thread to let things get stable on the bus. User::After(2000000); + if (gSupportResouceAllocationV2) + { + test.Next(_L("endpoint 1 resource allocation results(resource allocation V2)")); + TBool res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDoubleBuffering); + test.Printf(_L("Double Buffering on endpoint 1 %s\n"), + res ? _S("now allocated") : _S("not allocated")); + + res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDMA); + test.Printf(_L("DMA on endpoint 1 %s\n"), + res ? _S("still allocated") : _S("not allocated")); + } + test.End(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/device/t_usbco2.cpp --- a/kerneltest/e32test/device/t_usbco2.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/device/t_usbco2.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -31,7 +31,7 @@ _LIT(KFileName, "\\T_USBFILE.BIN"); _LIT(KActivePanic, "T_USB"); -static const TUint32 KTusbVersion = 20070524; // just an edit date really +static const TUint32 KTusbVersion = 20091224; // just an edit date really static const TUint8 KUsbrflctVersionMajor = 1; // the version we're compatible with static const TUint8 KUsbrflctVersionMinor = 5; static const TUint8 KUsbrflctVersionMicro = 0; @@ -52,9 +52,12 @@ iBufferSizeChosen(EFalse), iBandwidthPriorityChosen(EFalse), iDMAChosen(EFalse), + iAllocateDma(EFalse), iDoubleBufferingChosen(EFalse), + iAllocateDoubleBuffering(EFalse), iSoftwareConnect(EFalse), iHighSpeed(EFalse), + iResourceAllocationV2(EFalse), iOtg(EFalse), iVerbose(aVerboseOutput) {} @@ -112,7 +115,18 @@ return; } TUSB_PRINT("Created reader/writer"); - + + // check for endpoint resource allocation v2 support + TUsbDeviceCaps d_caps; + r = iPort.DeviceCaps(d_caps); + if (r != KErrNone) + { + TUSB_PRINT1("Error %d on querying device capabilities", r); + User::Leave(-1); + return; + } + iResourceAllocationV2 = ((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0); + // Check for OTG support TBuf8 otg_desc; r = iPort.GetOtgDescriptor(otg_desc); @@ -373,14 +387,17 @@ } TUSB_PRINT1("(Set to 0x%08X)", iBandwidthPriority); iBandwidthPriorityChosen = ETrue; - - TUSB_PRINT("Configuring interface..."); - TInt r = SetupInterface(); - if (r != KErrNone) + + if (!iResourceAllocationV2) { - TUSB_PRINT1("Error: %d. Stopping active scheduler...", r); - CActiveScheduler::Stop(); - return; + TUSB_PRINT("Configuring interface..."); + TInt r = SetupInterface(); + if (r != KErrNone) + { + TUSB_PRINT1("Error: %d. Stopping active scheduler...", r); + CActiveScheduler::Stop(); + return; + } } } else if (!iDMAChosen) @@ -389,15 +406,27 @@ switch (aChar) { case '1': + { TUSB_PRINT("- Trying to deallocate endpoint DMA:\n"); - DeAllocateEndpointDMA(EEndpoint1); - DeAllocateEndpointDMA(EEndpoint2); + if (!iResourceAllocationV2) + { + DeAllocateEndpointDMA(EEndpoint1); + DeAllocateEndpointDMA(EEndpoint2); + } + iAllocateDma = EFalse; break; + } case '2': + { TUSB_PRINT("- Trying to allocate endpoint DMA:\n"); - AllocateEndpointDMA(EEndpoint1); - AllocateEndpointDMA(EEndpoint2); + if (!iResourceAllocationV2) + { + AllocateEndpointDMA(EEndpoint1); + AllocateEndpointDMA(EEndpoint2); + } + iAllocateDma = ETrue; break; + } default: TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint()); goto request_char; @@ -410,20 +439,44 @@ switch (aChar) { case '1': + { TUSB_PRINT("- Trying to deallocate Double Buffering:\n"); - DeAllocateDoubleBuffering(EEndpoint1); - DeAllocateDoubleBuffering(EEndpoint2); + if (!iResourceAllocationV2) + { + DeAllocateDoubleBuffering(EEndpoint1); + DeAllocateDoubleBuffering(EEndpoint2); + } + iAllocateDoubleBuffering = EFalse; break; + } case '2': + { TUSB_PRINT("- Trying to allocate Double Buffering:\n"); - AllocateDoubleBuffering(EEndpoint1); - AllocateDoubleBuffering(EEndpoint2); + if (!iResourceAllocationV2) + { + AllocateDoubleBuffering(EEndpoint1); + AllocateDoubleBuffering(EEndpoint2); + } + iAllocateDoubleBuffering = ETrue; break; + } default: TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint()); goto request_char; } iDoubleBufferingChosen = ETrue; + + if (iResourceAllocationV2) + { + TUSB_PRINT("Configuring interface..."); + TInt r = SetupInterface(); + if (r != KErrNone) + { + TUSB_PRINT1("Error: %d. Stopping active scheduler...", r); + CActiveScheduler::Stop(); + return; + } + } // Everything chosen, so let's re-enumerate... TUSB_PRINT("Enumeration..."); @@ -682,6 +735,20 @@ return KErrGeneral; } + if (iResourceAllocationV2) + { + if (iAllocateDma) + { + ifc().iEndpointData[0].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; + ifc().iEndpointData[1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; + } + if (iAllocateDoubleBuffering) + { + ifc().iEndpointData[0].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DoubleBuffering; + ifc().iEndpointData[1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DoubleBuffering; + } + } + _LIT16(ifcname, "T_USB Test Interface (Default Setting 0)"); ifc().iString = const_cast(&ifcname); ifc().iTotalEndpointsUsed = 2; @@ -1775,6 +1842,7 @@ TUSB_PRINT1("Device State notifier: Alternate interface setting has changed: now %d", iDeviceState & ~KUsbAlternateSetting); } + Activate(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/bld.inf --- a/kerneltest/e32test/group/bld.inf Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/group/bld.inf Sat Feb 20 00:10:51 2010 +0200 @@ -37,10 +37,10 @@ ../dll/d_ldrtst.h /epoc32/include/ -../nkernsa/interrupts.h /epoc32/include/nktest/ // -../nkernsa/nkutils.h /epoc32/include/nktest/ // -../nkernsa/utils.h /epoc32/include/nktest/ // -../nkernsa/diag.h /epoc32/include/nktest/ // +../nkernsa/interrupts.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(nktest/interrupts.h) // +../nkernsa/nkutils.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(nktest/nkutils.h) // +../nkernsa/utils.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(nktest/utils.h) // +../nkernsa/diag.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(nktest/diag.h) // ../../../kernel/eka/include/e32huffman.h /epoc32/include/ @@ -69,6 +69,7 @@ ../dll/oe/eabi/urel/t_oeexport1.exe /epoc32/release/armv5/urel/t_oeexport1.exe ../demandpaging/d_pagestress.h /epoc32/include/ +../pci/t_pci.h /epoc32/include/e32test/t_pci.h ../iic/iic_psl/i2c.h /epoc32/include/e32test/ ../iic/iic_psl/spi.h /epoc32/include/e32test/ @@ -117,6 +118,7 @@ d_shbuf_client support d_shbuf_own support d_asid support +d_entropysources support #ifdef GENERIC_MARM d_schedhook support @@ -482,6 +484,11 @@ t_heapdb t_kheap +// Secure RNG tests +t_securerng +t_sha256 +t_entropysources + // /E32TEST/LFFS tests t_lfsdrv2 manual t_lfsdrvbm manual @@ -999,3 +1006,6 @@ d_mmcsc support #include "../hcr/hcr.inf" + +//pci tests +t_pci diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/d_entropysources.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/group/d_entropysources.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,34 @@ +// Copyright (c) 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\d_entropysources.mmp +// +// + +#include "kernel/kern_ext.mmh" + +target d_entropysources.ldd +targettype ldd + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN +userinclude ../../../kernel/eka/include/kernel +sourcepath ../random +source d_entropysources.cpp + +start wins +win32_headers +end + +capability all +vendorid 0x70000001 +SMPSAFE diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/t_entropysources.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/group/t_entropysources.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,30 @@ +// Copyright (c) 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: +// Tests whether the device has good enough entropy sources or not. +// +// + +TARGET t_entropysources.exe +TARGETTYPE EXE +UID 0x2000A3D2 0xA000D320 +VENDORID 0x70000001 + +SOURCEPATH ../random +SOURCE t_entropysources.cpp + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +LIBRARY euser.lib hal.lib +SMPSAFE +CAPABILITY all diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/t_pci.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/group/t_pci.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,27 @@ +// Copyright (c) 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_pci.mmp + +TARGET t_pci.exe +TARGETTYPE EXE +SOURCEPATH ../pci +SOURCE t_pci.cpp +LIBRARY euser.lib +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +CAPABILITY ReadDeviceData WriteDeviceData + +VENDORID 0x70000001 + +SMPSAFE diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/t_securerng.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/group/t_securerng.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,31 @@ +// Copyright (c) 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. +// +// Description: +// e32test/group/t_securerng.mmp +// + + +TARGET t_securerng.exe +TARGETTYPE EXE + + +UID 0 0x2000A3D7 + +SOURCEPATH ../random +SOURCE t_securerng.cpp + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +LIBRARY euser.lib + +VENDORID 0x70000001 +SMPSAFE + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/group/t_sha256.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/group/t_sha256.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,36 @@ +// Copyright (c) 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/tsha256.mmp +// +// + +TARGET t_sha256.exe +TARGETTYPE EXE + + +UID 0 0x2000A3D7 + +SOURCEPATH ../random +SOURCE t_sha256.cpp +SOURCE ../../../kernel/eka/kernel/sha256.cpp + + +USERINCLUDE ../../../kernel/eka/include/kernel + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +LIBRARY euser.lib + +VENDORID 0x70000001 +SMPSAFE diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/heap/t_heap.cpp --- a/kerneltest/e32test/heap/t_heap.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/heap/t_heap.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -529,7 +529,12 @@ for(TInt aSize2=(TInt)pHeap->AllocLen(aCell); aSize2>=0; aSize2--) { test(pHeap->ReAlloc(aCell, aSize2)!=NULL); - test(((TInt)pHeap->AllocLen(aCell)>=aSize2)&&((TInt)pHeap->AllocLen(aCell)<=aSize2+KMinFreeSize)); + + test((TInt)pHeap->AllocLen(aCell)>=aSize2); + + TInt aTmpSize2 = Max(_ALIGN_UP(aSize2 + RHeap::EAllocCellSize, KAlign), KMinFreeSize); + + test((TInt)pHeap->AllocLen(aCell)<=aTmpSize2+KMinFreeSize); } pHeap->Check(); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/misc/test_thread.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/misc/test_thread.h Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,240 @@ +// Copyright (c) 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. +// +// Description: Some helper classes to assist with writing multi-threaded tests + +#ifndef TEST_THREAD_H +#define TEST_THREAD_H + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include +#include +#include +#include +#include + + +_LIT(KPciPanicCat, "test_thread.h"); + +static const TInt KPciHeapSize=0x2000; + +enum TPciPanicCode + { + EThreadCreateFailed + }; + +/** +A utility class for running functions in other threads/processes +*/ +class TTestRemote + { +public: + virtual TInt WaitForExitL() = 0; + virtual ~TTestRemote() + {} + + virtual void Rendezvous(TRequestStatus& aStatus) = 0; + +protected: + TTestRemote() + {} + + static TInt RunFunctor(TAny* aFunctor) + { + TFunctor& functor = *(TFunctor*)aFunctor; + functor(); + return KErrNone; + } + + TRequestStatus iLogonStatus; + static TInt iCount; + }; +TInt TTestRemote::iCount=0; + +class TTestThread : public TTestRemote + { +public: + TTestThread(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume=ETrue) + { + Init(aName, aFn, aData, aAutoResume); + } + + /** + Run aFunctor in another thread + */ + TTestThread(const TDesC& aName, TFunctor& aFunctor, TBool aAutoResume=ETrue) + { + Init(aName, RunFunctor, &aFunctor, aAutoResume); + } + + ~TTestThread() + { + //RTest::CloseHandleAndWaitForDestruction(iThread); + iThread.Close(); + } + + void Resume() + { + iThread.Resume(); + } + + /** + If thread exited normally, return its return code + Otherwise, leave with exit reason + */ + virtual TInt WaitForExitL() + { + User::WaitForRequest(iLogonStatus); + const TInt exitType = iThread.ExitType(); + const TInt exitReason = iThread.ExitReason(); + + __ASSERT_ALWAYS(exitType != EExitPending, User::Panic(_L("TTestThread"),0)); + + if(exitType != EExitKill) + User::Leave(exitReason); + + return exitReason; + } + + virtual void Rendezvous(TRequestStatus& aStatus) + { + iThread.Rendezvous(aStatus); + } + +private: + void Init(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume) + { + TKName name(aName); + name.AppendFormat(_L("-%d"), iCount++); + TInt r=iThread.Create(name, aFn, KDefaultStackSize, KPciHeapSize, KPciHeapSize, aData); + if(r!=KErrNone) + { + RDebug::Printf("RThread::Create failed, code=%d", r); + User::Panic(KPciPanicCat, EThreadCreateFailed); + } + + iThread.Logon(iLogonStatus); + __ASSERT_ALWAYS(iLogonStatus == KRequestPending, User::Panic(_L("TTestThread"),0)); + + if(aAutoResume) + iThread.Resume(); + } + + RThread iThread; + }; + +class CTest : public CBase, public TFunctor + { +public: + ~CTest() + { + iName.Close(); + } + + virtual void operator()() + { + RTest test(iName); + test.Start(iName); + for(TInt i=0; i testArray; + RPointerArray threadArray; + + for(TInt i=0; iWaitForExitL()); + if(leaveCode != KErrNone) + { + test.Printf(_L("Thread %d: Panic code:%d\n"), j, leaveCode); + test_KErrNone(leaveCode); + } + + if(r!=KErrNone) + { + test.Printf(_L("Thread Number %d\n"), j); + test_KErrNone(r); + } + } + + threadArray.ResetAndDestroy(); + threadArray.Close(); + + testArray.ResetAndDestroy(); + testArray.Close(); + } + +#endif //TEST_THREAD_H + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/mmu/t_cache.cpp --- a/kerneltest/e32test/mmu/t_cache.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/mmu/t_cache.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -310,18 +310,17 @@ DoTest4(RCacheTestDevice::E_Normal_Cached, dC, timeNS, timeS); test.Printf(_L("Normal_Cached %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); + DoTest4(RCacheTestDevice::E_KernelInternal4, dC, timeNS, timeS); + test.Printf(_L("KernelInternal4 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); + DoTest4(RCacheTestDevice::E_PlatformSpecific5, dC, timeNS, timeS); + test.Printf(_L("PlatSpecific5 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); + DoTest4(RCacheTestDevice::E_PlatformSpecific6, dC, timeNS, timeS); + test.Printf(_L("PlatSpecific6 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); + DoTest4(RCacheTestDevice::E_PlatformSpecific7, dC, timeNS, timeS); + test.Printf(_L("PlatSpecific7 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); + if(CacheInfo.iMemoryRemapping) { - DoTest4(RCacheTestDevice::E_KernelInternal4, dC, timeNS, timeS); - test.Printf(_L("KernelInternal4 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); - DoTest4(RCacheTestDevice::E_PlatformSpecific5, dC, timeNS, timeS); - test.Printf(_L("PlatSpecific5 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); - DoTest4(RCacheTestDevice::E_PlatformSpecific6, dC, timeNS, timeS); - test.Printf(_L("PlatSpecific6 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); - DoTest4(RCacheTestDevice::E_PlatformSpecific7, dC, timeNS, timeS); - test.Printf(_L("PlatSpecific7 %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); - - DoTest4(RCacheTestDevice::E_InnerWT_Remapped, dC, timeNS, timeS); test.Printf(_L("InnerWT_Remap %08xH\t%7d\t%7d\n"),dC.iActualMapAttr, timeNS, timeS); DoTest4(RCacheTestDevice::E_InnerWBRA_Remapped, dC, timeNS, timeS); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/mmu/t_codepaging.cpp --- a/kerneltest/e32test/mmu/t_codepaging.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/mmu/t_codepaging.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -698,7 +698,7 @@ r=file.BlockMap(info,start, -1,ETestDebug); if (r!=KErrNone && r!=KErrCompletion) - test.Printf(_L("Error %d: could not obtain block map\n"),r); + test.Printf(_L("Error %d: could not obtain block map for file %S\n"),r, &libname); test(r==KErrNone || r==KErrCompletion); TInt locDriveNumber=info.iLocalDriveNumber; @@ -1746,7 +1746,18 @@ l.Close(); CopyDllsToSupportedDrives(); - + + // Set Code Paging Cache to a known size compatable with this test + TInt pageSize = 0; + test_noError(UserHal::PageSizeInBytes(pageSize)); + TUint cacheOriginalMin = 0, cacheOriginalMax = 0, cacheCurrentSize = 0; + const TUint kCacheNewMin = 64, kCacheNewMax = 256; + test.Printf(_L("Change cache size to Min:%d, Max:%d pages for duration of test\n"), kCacheNewMin, kCacheNewMax ); + + //store original values + DPTest::CacheSize(cacheOriginalMin, cacheOriginalMax, cacheCurrentSize); + test_KErrNone(DPTest::SetCacheSize(kCacheNewMin*pageSize, kCacheNewMax*pageSize)); + Initialise(); StartOtherProcess(2, OtherProcess); @@ -1755,6 +1766,11 @@ OtherProcess.Kill(); OtherProcess.Close(); + + //Restore the cache size to original values + test.Printf(_L("Reset cache size to original values Min:%d Max:%d pages\n"), cacheOriginalMin/pageSize, cacheOriginalMax/pageSize); + test_KErrNone(DPTest::SetCacheSize(cacheOriginalMin, cacheOriginalMax)); + test.End(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/pci/t_pci.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/pci/t_pci.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,865 @@ +// Copyright (c) 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: +// This is a test for the PCI driver, so far implemented only on the +// Naviengine platform. It aims to test: +// -That known values of data in config and memory space, on a given +// device can be read as expected. +// -That data can be written and modified in config and memory space +// -PCI memory buffers mapped or allocated by the PCI driver work as +// expected. These are +// -DChunk created by PCI driver and accessible from PCI +// -DPlatHwChunk created by PCI driver and accessible from PCI +// -DChunk created externally, then mapped in to PCI memory space +// There are tests to: +// - Create and close each buffer. Heap checking ensures proper +// cleanup +// - Create and close multiple buffers from multiple threads. +// This is an SMP focused test to check that the implementation +// of the chunk manager and allocator in the driver are thread +// safe. The tests should pass without triggering any assertions in +// the driver's invariance checks. +// - Write to buffers from software, and read back via the +// system to PCI window, and vice-versa -- a loop-back test. +// This checks that PCI buffers are indeed accessible to PCI devices. +// +// The tests require several pieces of PSL specific information: +// - A TPciDevice containing the vendor and device IDs of a PCI device +// to use for testing. +// - TAddrSpaceTests which identify regions of a device's config and +// memory space with known values, or which are known to be writable. +// +// The test driver grants access to the PCI API with the following +// constructs: +// - TUserConfigSpace and TUserMemorySpace, derived from TUserPciSpace, +// which are user side equivalents of kernel-side objects allowing +// accesses of different sizes to a PCI device's config space or +// memory space. +// - RPciChunk which is derived from and RChunk and corresponds to +// a kernel-side DChunk, which in turn corresponds to a PCI chunk or +// buffer. The test driver uses these for all PCI chunk types (a +// "wrapper" DChunk is used to map the memory of a PCI DPlatHwChunk +// to user side). +// +// Known Issues: +// The test driver d_pci is intended to be platform independent but +// for now still contains some PSL specific information .eg the test +// info structure (which should really be passed up from the PSL) and +// the address and size of the system to pci window. For now the +// test driver code will remain in the Naviengine baseport directory. +// If the PCI driver is ever ported to a new platform this can be +// rectified. +// +// +// +#include "../misc/test_thread.h" +#include +#define __E32TEST_EXTENSION__ +#include +#include "t_pci.h" +#include + +class RPci; +/** +Extends RChunk to hold the PCI address +associated with a chunk. +*/ +class RPciChunk: public RChunk + { +public: + TUint PciBase() + { + return iPciBaseAddr; + } + + /** + Return the PCI accessible size + */ + TInt Size() const + { + return iPciSize; + } + +private: + friend class RPci; + TUint iPciBaseAddr; + TInt iPciSize; //size of the region mapped into PCI + }; + +typedef TInt (RPci::*ChunkOpenFn)(RPciChunk&, TInt, TRequestStatus*); + +class RPci : public RBusLogicalChannel + { +public: + TInt Open(); + TInt GetTestInfo(TPciTestInfo& aTestInfo); + + TInt Open(const TPciDevice&); + + TUint AccessConfigSpace(const TUserConfigSpace& aCs); + TUint AccessMemorySpace(const TUserMemorySpace& aMs); + TInt OpenPciDChunk(RPciChunk& aPciChunk,TInt aPciChunkSize, TRequestStatus* aStatus=0); + TInt OpenPciPlatHwChunk(RPciChunk& aPciHwChunk,TInt aPciChunkSize, TRequestStatus* aStatus=0); + TInt OpenPciMappedChunk(RPciChunk& aPciMappedChunk,TInt aPciChunkSize, TRequestStatus* aStatus=0); + TInt OpenPciWindowChunk(RChunk& aPciWindowChunk); + TInt RunUnitTests(); +private: + TInt DoOpenPciChunk(RPciChunk& aPciChunk, TInt aPciChunkSize, TPciTestCmd aCmd, TRequestStatus* aStatus); + }; + +inline TInt RPci::Open() + { + return DoCreate(KPciLddFactory, TVersion(), KNullUnit, NULL, NULL); + } + +inline TInt RPci::Open(const TPciDevice& aDevice) + { + TPckgC devicePkg(aDevice); + return DoCreate(KPciLddFactory, TVersion(), KNullUnit, NULL, &devicePkg); + } + +inline TInt RPci::GetTestInfo(TPciTestInfo& aTestInfo) + { + TPckg info(aTestInfo); + return DoControl(EGetTestInfo, &info); + } + +inline TInt RPci::RunUnitTests() + { + return DoControl(ERunUnitTests); + } + +TUint RPci::AccessConfigSpace(const TUserConfigSpace& aCs) + { + TPckgC pkg(aCs); + return DoControl(EAccessConfigSpace, &pkg); + } + +TUint RPci::AccessMemorySpace(const TUserMemorySpace& aMs) + { + TPckgC pkg(aMs); + return DoControl(EAccessMemorySpace, &pkg); + } + +TInt RPci::OpenPciDChunk(RPciChunk& aPciChunk,TInt aPciChunkSize, TRequestStatus* aStatus) + { + return DoOpenPciChunk(aPciChunk, aPciChunkSize, EOpenPciDChunk, aStatus); + } + +TInt RPci::OpenPciPlatHwChunk(RPciChunk& aPciHwChunk,TInt aPciChunkSize, TRequestStatus* aStatus) + { + return DoOpenPciChunk(aPciHwChunk, aPciChunkSize, EOpenPciPlatHwChunk, aStatus); + } + +TInt RPci::OpenPciMappedChunk(RPciChunk& aPciMappedChunk,TInt aPciChunkSize, TRequestStatus* aStatus) + { + return DoOpenPciChunk(aPciMappedChunk, aPciChunkSize, EOpenPciMappedChunk, aStatus); + } + +TInt RPci::OpenPciWindowChunk(RChunk& aPciWindowChunk) + { + TUint chunkHandle = DoControl(EOpenPciWindowChunk); + return aPciWindowChunk.SetReturnedHandle(chunkHandle); + } + +TInt RPci::DoOpenPciChunk(RPciChunk& aPciChunk, TInt aPciChunkSize, TPciTestCmd aCmd, TRequestStatus* aStatus) + { + const TInt constPciChunkSize = aPciChunkSize; + TPciChunkCreateInfo info(constPciChunkSize, aPciChunk.iPciBaseAddr, aStatus); + TPckgC pkg(info); + + TUint chunkHandle = DoControl(aCmd, &pkg); + + const TInt r = aPciChunk.SetReturnedHandle(chunkHandle); + if(r == KErrNone) + { + aPciChunk.iPciSize = constPciChunkSize; + } + return r; + } + +TUserPciSpace::TUserPciSpace(RPci& aPci) + :iPci(&aPci) + {} + +TUserConfigSpace::TUserConfigSpace(RPci& aPci) + :TUserPciSpace(aPci) + {} + +TUint TUserConfigSpace::Call() + { + return iPci->AccessConfigSpace(*this); + } + +TUserPciSpace* TUserConfigSpace::Clone() const + { + return new TUserConfigSpace(*this); + } + +TUserMemorySpace::TUserMemorySpace(RPci& aPci, TInt aBarIndex) + :TUserPciSpace(aPci), iBarIndex(aBarIndex) + {} + +TUint TUserMemorySpace::Call() + { + return iPci->AccessMemorySpace(*this); + } + +TUserPciSpace* TUserMemorySpace::Clone() const + { + return new TUserMemorySpace(*this); + } + +/** +Test address allocator +*/ +TInt TestRunPciUnitTest(RPci& pci) + { + return pci.RunUnitTests(); + } + + +/** +Read from a defined address in memory or config space, compare against expected values. +8,16, and 32 bit accesses performed. + +@param aSpace Object gving access to either the config or memory space of a PCI device +@param aInfo Contains the address and expected value of a dword +*/ +void TestReadAddressSpace(TUserPciSpace& aSpace, const TPciTestInfo::TAddrSpaceTest& aInfo, RTest& test, TBool aVerbose=EFalse) + { + const TUint os = aInfo.iOffset; + //Iterate over different widths, and possible + //subfields of 32 bit word + for(TInt bitWidth=32; bitWidth>=8; bitWidth>>=1) + { + const TInt numberOfFields = (32/bitWidth); + for(TInt i=0; i< numberOfFields; i++) + { + const TInt extraByteOffset = i * (bitWidth >> 3); + const TInt byteOffset = os + extraByteOffset; + if(aVerbose) + test.Printf(_L("Access bitWidth=%d byte offset=%d\n"), bitWidth, byteOffset); + + const TUint expected = aInfo.Expected(bitWidth, byteOffset); + const TUint read = aSpace.Read(bitWidth, byteOffset); + if(aVerbose) + test.Printf(_L("expect 0x%08x, read 0x%08x\n"), expected, read); + test_Equal(expected, read); + } + } + } + +/** +Verify writes and modifications to a defined address in memory or config space. 8,16, and 32 bit +accesses performed. + +@param aSpace Object gving access to either the config or memory space of a PCI device +@param aInfo Contains the address of a (at least partially) writable dword +*/ +void TestWriteAddressSpace(TUserPciSpace& aSpace, TPciTestInfo::TAddrSpaceTest& aInfo, RTest& test, TBool aVerbose=EFalse) + { + const TUint original = aSpace.Read(32, aInfo.iOffset); + const TUint os = aInfo.iOffset; + TUint mask = ~aInfo.iReadOnlyMask; + + //The pattern will be truncated when used with bit widths + //less than 32. + const TUint initPattern = 0xFFFFFFFF; + + for(TInt bitWidth=32; bitWidth>=8; bitWidth>>=1) + { + const TUint pattern = initPattern >> (32-bitWidth); + const TInt numberOfFields = (32/bitWidth); + for(TInt i=0; i< numberOfFields; i++) + { + const TInt extraByteOffset = i * (bitWidth >> 3); + const TInt byteOffset = os + extraByteOffset; + if(aVerbose) + test.Printf(_L("Access bitWidth=%d byte offset=%d\n"), bitWidth, byteOffset); + //the full dword we expect + //currently assume that the unwritable bits will be 0 + const TUint writeExpect = (pattern << (bitWidth * i) ) & mask; + const TUint clearExpect = 0; + + //do write followed by clear + const TUint expect[] = {writeExpect, clearExpect}; + const TUint write[] = {pattern, 0}; + for(TInt n = 0; n < 2; n++) + { + aSpace.Write(bitWidth, byteOffset, write[n]); + TUint result = aSpace.Read(32, os); + + if(aVerbose) + test.Printf(_L("wrote 0x%08x, expect 0x%08x, read 0x%08x\n"), + write[n], expect[n], result); + test_Equal(expect[n], result); + } + + //test Modify calls. Set then clear pattern + TUint set[] = {pattern, 0}; + TUint clear[] = {0, pattern}; + + for(TInt m = 0; m < 2; m++) + { + aSpace.Modify(bitWidth, byteOffset, clear[m], set[m]); + TUint result = aSpace.Read(32, os); + + if(aVerbose) + test.Printf(_L("clear 0x%08x, set 0x%08x, expect 0x%08x, read 0x%08x\n"), clear[m], set[m], expect[m], result); + test_Equal(expect[m], result); + } + } + } + + //restore orginal value or we will not be able to access device + aSpace.Write(32, os, original); + } + + +/** +Verify that a PCI DChunk can be opened and closed from user side + +@param pci The RPci object to use +@param test The RTest object to use +@param aPciChunkSize The size of the DChunk which would be created +*/ +void TestOpenAndCloseDChunk(RPci& pci,RTest& test,TInt aPciChunkSize) + { + RPciChunk testPciDChunk; + + // Create and open Chunk + TRequestStatus status; + TInt r = pci.OpenPciDChunk(testPciDChunk,aPciChunkSize, &status); + test_KErrNone(r); + + test(testPciDChunk.IsWritable()); + test(testPciDChunk.IsReadable()); + + test.Printf(_L("PCI Chunk base = 0x%08x\n"), testPciDChunk.Base()); + test.Printf(_L("PCI Chunk size = %d\n"), testPciDChunk.Size()); + test.Printf(_L("PCI Address = 0x%08x\n"), testPciDChunk.PciBase()); + + //Close Chunk + test.Next(_L("Close PCI Chunk handle")); + + RTest::CloseHandleAndWaitForDestruction(testPciDChunk); + User::WaitForRequest(status); + } + +/** +Verify that a PCI PlatHwChunk can be opened and closed from user side + + +@param pci The RPci object to use +@param test The RTest object to use +@param aPciChunkSize The size of the PlatHwChunk which would be created +*/ +void TestOpenAndClosePciPlatHwChunk(RPci& pci,RTest& test,TInt aPciChunkSize) + { + RPciChunk testPciPlatHwChunk; + + // Create and open Chunk + TRequestStatus status; + TInt r = pci.OpenPciPlatHwChunk(testPciPlatHwChunk,aPciChunkSize, &status); + test_KErrNone(r); + + test(testPciPlatHwChunk.IsWritable()); + test(testPciPlatHwChunk.IsReadable()); + + test.Printf(_L("PCI Chunk base = 0x%08x\n"), testPciPlatHwChunk.Base()); + test.Printf(_L("PCI Chunk size = %d\n"), testPciPlatHwChunk.Size()); + test.Printf(_L("PCI Address = 0x%08x\n"), testPciPlatHwChunk.PciBase()); + + //Close Chunk + testPciPlatHwChunk.Close(); + User::WaitForRequest(status); + test.Next(_L("Closed PCI PlatHwChunk handle")); + } + +/** +Verify that pci-mapped DChunk can be opended and closed form user side + +@param pci The RPci object to use +@param test The RTest object to use +@param aPciChunkSize The size of the pci-mapped DChunk which would be created +*/ +void TestPciMapppedChunk(RPci& pci,RTest& test,TInt aPciChunkSize) + { + RPciChunk testPciMappedChunk; + + // Create and open Chunk + TRequestStatus status; + TInt r = pci.OpenPciMappedChunk(testPciMappedChunk,aPciChunkSize, &status); + test_KErrNone(r); + + test(testPciMappedChunk.IsWritable()); + test(testPciMappedChunk.IsReadable()); + + test.Printf(_L("PCI Chunk base = 0x%08x\n"), testPciMappedChunk.Base()); + test.Printf(_L("PCI Chunk size = %d\n"), testPciMappedChunk.Size()); + test.Printf(_L("PCI Address = 0x%08x\n"), testPciMappedChunk.PciBase()); + + //Close Chunk + testPciMappedChunk.Close(); + User::WaitForRequest(status); + test.Next(_L("Closed PCI Mapped Chunk handle")); + } + +/** +Verify that an RChunk can be open to grant access to the internal PCI window from the user side + +@param pci The RPci object to use +@param test The RTest object to use +*/ +void TestPciWindowChunk(RPci& pci,RTest& test) + { + RChunk testPciWindowChunk; + + // Create and open DChunk + TInt r = pci.OpenPciWindowChunk(testPciWindowChunk); + test_KErrNone(r); + + test(testPciWindowChunk.IsWritable()); + test(testPciWindowChunk.IsReadable()); + + test.Printf(_L("PCI Window Chunk base = 0x%08x\n"), testPciWindowChunk.Base()); + test.Printf(_L("PCI Window Chunk size = %d\n"), testPciWindowChunk.Size()); + + //Close Chunk + testPciWindowChunk.Close(); + test.Next(_L("Closed PCI Window Chunk handle")); + } + + +class CPciTest : public CTest + { +protected: + CPciTest(const TDesC& aName, TInt aIterations, RPci& aDevice) + : CTest(aName, aIterations), iDevice(aDevice) + {} + + RPci iDevice; + }; + +/** +Each instance of test will open a chunk, using the function specified in +the template argument, FUNC. + +The total number of chunks that can be opened by all instances is limited +by iMaxCount. + +All intances of the test will hold their chunk open until iMaxCount has +been reached. +*/ +template +class CPciOpenChunkTest : public CPciTest + { +public: + CPciOpenChunkTest(const TDesC& aName, TInt aIterations, RPci& aDevice, + RSemaphore aSemOpen, RSemaphore aSemClose, RFastLock aLock, TInt aMaxCount) + :CPciTest(aName, aIterations, aDevice), + iSemOpen(aSemOpen), iSemClose(aSemClose), iLock(aLock), iMaxCount(aMaxCount) + { + } + + virtual void RunTest() + { + RTest test(iName); + RPciChunk chunk; + + iSemOpen.Wait(); + TRequestStatus status; + const TInt chunkSize = 0x400; + //open chunk by calling FUNC + TInt r = ((iDevice).*(FUNC))(chunk, chunkSize, &status); + test_KErrNone(r); + + iLock.Wait(); + iOpenCount++; + test.Printf(_L("Opened chunk %d\n"), iOpenCount); + if(iOpenCount == iMaxCount) + { + test.Printf(_L("Opened=%d, max=%d: Allow chunks to close\n"), iOpenCount, iMaxCount); + //release all waiting threads + //plus 1 preincrement so this + //thread also passes + iSemClose.Signal(iOpenCount); + iOpenCount = 0; + } + iLock.Signal(); + + + iSemClose.Wait(); + chunk.Close(); + User::WaitForRequest(status); + + // permit another chunk to be opened + iSemOpen.Signal(); + test.Close(); + } + + virtual CTest* Clone() const + { + //make shallow copy + return new CPciOpenChunkTest(*this); + } + + +private: + RSemaphore& iSemOpen; ///!< Represents the number of available PCI mappings + RSemaphore& iSemClose; ///!< Represents the number of threads waiting to close their chunk + RFastLock& iLock; + static TInt iOpenCount; + const TInt iMaxCount; + }; + +template +TInt CPciOpenChunkTest::iOpenCount = 0; + + +/** +Test which will perform various reads from a PCI address +space (config or memory) and confirm that values are read +as expected +*/ +class CPciAddressSpaceRead : public CPciTest + { +public: + CPciAddressSpaceRead(const TDesC& aName, TInt aIterations, RPci& aDevice, + const TUserPciSpace& aSpace, const TPciTestInfo::TAddrSpaceTest& aInfo) + :CPciTest(aName, aIterations, aDevice), + iAddressSpace(aSpace.Clone()), iSpaceTestInfo(aInfo) + { + } + + CPciAddressSpaceRead(const CPciAddressSpaceRead& aOther) + :CPciTest(aOther)/* TODO-REVIEW have object-sliced aOther - is this ok?*/, + iAddressSpace(aOther.iAddressSpace->Clone()), iSpaceTestInfo(aOther.iSpaceTestInfo) + { + } + + virtual ~CPciAddressSpaceRead() + { + delete iAddressSpace; + } + + virtual void RunTest() + { + __UHEAP_MARK; + RTest test(iName); + TestReadAddressSpace(*iAddressSpace, iSpaceTestInfo, test); + test.Close(); + __UHEAP_MARKEND; + } + + virtual CTest* Clone() const + { + //make shallow copy + return new CPciAddressSpaceRead(*this); + } + +private: + TUserPciSpace* iAddressSpace; + const TPciTestInfo::TAddrSpaceTest& iSpaceTestInfo; + }; + +/** +For aBuffer, test writing to it then reading back from aWindow +then write via window and read back from chunk + +@param test The RTest object to use +@param aBuffer RChunk corresponding to a PCI accessible buffer +@param aWindow RChunk coressponding an appropriate System-to-PCI memory window +It is presumed to start at PCI address 0 +*/ +void DoLoopBackTest(RTest& test, RPciChunk aBuffer, RChunk aWindow) + { + test.Start(_L("Test accessing memory via PCI")); + + TUint8* const bufferBase = aBuffer.Base(); + const TUint bufferSize = aBuffer.Size(); + const TUint bufferPciBase = aBuffer.PciBase(); + + TUint8* const windowBase = aWindow.Base(); + const TUint windowSize = aWindow.Size(); + +#define PRINT(N) RDebug::Printf("%s = 0x%08x (%d)", #N, (N), (N)) + PRINT(bufferBase); + PRINT(bufferSize); + PRINT(bufferPciBase); + + PRINT(windowBase); + PRINT(windowSize); + +#undef PRINT + + //need to check that the end of the buffer + //is within the windowed region + test(bufferPciBase + bufferSize <= windowSize); + TUint8* const bufferBaseWithinWindow = windowBase + bufferPciBase; + + test.Next(_L("write chunk")); + for(TUint i = 0; i < bufferSize; ++i) + { + //each byte will hold its own offset modulo 256 + bufferBase[i] = (TUint8)i; + } + + test.Next(_L("read back via window")); + for(TUint j=0; j < bufferSize; ++j) + { + const TUint8 result = bufferBaseWithinWindow[j]; + test_Equal(j%256, result); + } + + //clear chunk + memclr(bufferBase, bufferSize); + test.Next(_L("write via window")); + for(TUint k=0; k < bufferSize; ++k) + { + //each byte will hold its own offset modulo 256 + bufferBaseWithinWindow[k] = (TUint8)k; + } + + test.Next(_L("read back from chunk")); + for(TUint l=0; l < bufferSize; ++l) + { + const TUint8 result = bufferBase[l]; + test_Equal(l%256, result); + } + + test.End(); + } + +/** +Take care of opening a chunk, running the test and closing +*/ +template +inline void LoopBackTest(RPci& aPci, RTest& test, RChunk& aWindow) + { + RPciChunk pciChunk; + const TInt chunkSize = 0x400; //1k + + //call the specified chunk opening function + TRequestStatus status; + TInt r = ((aPci).*(OPEN_FUNC))(pciChunk, chunkSize, &status); + test_KErrNone(r); + DoLoopBackTest(test, pciChunk, aWindow); + pciChunk.Close(); + User::WaitForRequest(status); + } + +/** +Run the loopback test for the 3 types of buffer supported by the PCI driver. +DChunk +DPlatChunk +Mapped In external memory +*/ +void TestLoopBack(RPci& aPci, RTest& test) + { + test.Next(_L("Open PCI window")); + RChunk window; + + TInt r = aPci.OpenPciWindowChunk(window); + test_KErrNone(r); + + test.Next(_L("DChunk")); + LoopBackTest<&RPci::OpenPciDChunk>(aPci, test, window); + + test.Next(_L("DPlatHwChunk")); + LoopBackTest<&RPci::OpenPciPlatHwChunk>(aPci, test, window); + + test.Next(_L("DChunk (mapped in)")); + LoopBackTest<&RPci::OpenPciMappedChunk>(aPci, test, window); + + window.Close(); + } +#ifndef __VC32__ //visual studio 6 doesn't approve of pointer to member function template parameters +/** +Run the CPciOpenChunkTest for each type of chunk. This function also creates (and destroys) the +necessary semaphores and locks. +CPciOpenChunkTest objects are run in multiple threads using MultipleTestRun(). + +@param aDevice Handle to the test driver +@param test RTest to use. +@param aBufferLimit The maximum number of buffers which can be opened simultaneously +*/ +void TestBufferOpenConcurrency(RPci& aDevice, RTest& test, TInt aBufferLimit) + { + RSemaphore semaphoreOpen; + RSemaphore semaphoreClose; + RFastLock lock; + + TInt r = semaphoreOpen.CreateLocal(aBufferLimit); + test_KErrNone(r); + + r = semaphoreClose.CreateLocal(0); + test_KErrNone(r); + + r = lock.CreateLocal(); + test_KErrNone(r); + + const TInt iterations = 3; + { + test.Printf(_L("Opening %d PCI DChunks in %d threads\n"), aBufferLimit, aBufferLimit); + CPciOpenChunkTest<&RPci::OpenPciDChunk> + dChunkTest(_L("Concurrent-DChunk"), iterations, aDevice, semaphoreOpen, semaphoreClose, lock, aBufferLimit); + + MultipleTestRun(test, dChunkTest, aBufferLimit); + } + + { + test.Printf(_L("Opening %d PCI DPlatHwChunks in %d threads\n"), aBufferLimit, aBufferLimit); + CPciOpenChunkTest<&RPci::OpenPciPlatHwChunk> + platChunkTest(_L("Concurrent-DPlatHwChunk"), iterations, aDevice, semaphoreOpen, semaphoreClose, lock, aBufferLimit); + + MultipleTestRun(test, platChunkTest, aBufferLimit); + } + + { + test.Printf(_L("Opening %d PCI Mapped chunks in %d threads\n"), aBufferLimit, aBufferLimit); + CPciOpenChunkTest<&RPci::OpenPciMappedChunk> + mappedChunkTest(_L("Concurrent-DChunk(mapped)"), iterations, aDevice, semaphoreOpen, semaphoreClose, lock, aBufferLimit); + + MultipleTestRun(test, mappedChunkTest, aBufferLimit); + } + + semaphoreOpen.Close(); + semaphoreClose.Close(); + lock.Close(); + } +#endif + +TInt E32Main() + { + __UHEAP_MARK; + + _LIT(KPci, "PCI"); + RTest test(KPci); + test.Start(_L("Running PCI tests\n")); + + TInt r = User::LoadLogicalDevice(KPciLdd); + + __KHEAP_MARK; + + if(r==KErrNotFound) + { + test.Printf(_L("No PCI system present - skipping test\n")); + return KErrNone; + } + if(r!=KErrNone && r!=KErrAlreadyExists) + { + test_KErrNone(r); + } + + test.Next(_L("Open non-existant device\n")); + RPci device; + TPciDevice unavailable; + r = device.Open(unavailable); + test_Equal(KErrNotFound, r); + + RPci pciInfo; + r = pciInfo.Open(); + test_KErrNone(r); + + test.Next(_L("Get test info from driver\n")); + TPciTestInfo info; + r = pciInfo.GetTestInfo(info); + test_KErrNone(r); + pciInfo.Close(); + + test.Next(_L("Open test device\n")); + r = device.Open(info.iDevice); + test_KErrNone(r); + + test.Next(_L("Run Device Unit Test\n")); + r=TestRunPciUnitTest(device); + test_KErrNone(r); + + test.Next(_L("Read config space\n")); + TUserConfigSpace cs(device); + TestReadAddressSpace(cs, info.iCfgSpaceRead, test); + + test.Next(_L("Write config space\n")); + TestWriteAddressSpace(cs, info.iCfgSpaceWrite, test); + + test.Next(_L("Read memory space\n")); + TUserMemorySpace ms(device, info.iMemSpaceIndex); + TestReadAddressSpace(ms, info.iMemSpaceRead, test); + + test.Next(_L("Modify memory space\n")); + TestWriteAddressSpace(ms, info.iMemSpaceWrite, test); + + { + const TInt addrSpaceThreadCount = 4; + const TInt iterations = 100; + test.Next(_L("Concurrent config space reads")); + CPciAddressSpaceRead cfgSpaceRead(_L("Cfg Space Read"), iterations, device, cs, info.iCfgSpaceRead); + MultipleTestRun(test, cfgSpaceRead, addrSpaceThreadCount); + + test.Next(_L("Concurrent memory space reads")); + CPciAddressSpaceRead memSpaceRead(_L("Memory Space Read"), iterations, device, ms, info.iMemSpaceRead); + MultipleTestRun(test, memSpaceRead, addrSpaceThreadCount); + } + + TInt testDChunkSize = 0x4000; + test.Next(_L("Open and Close DChunks\n")); + TestOpenAndCloseDChunk(device,test,testDChunkSize); + + TInt testDPlatChunkSize = 0x2000; + test.Next(_L("Open and Close PlatHwChunks\n")); + TestOpenAndClosePciPlatHwChunk(device,test,testDPlatChunkSize); + + //TestPciMapppedChunk() fails for sizes greater than 4K. + //The issue is that a block of externally mapped memory must be + //naturally alligned in order to be accessible to the PCI bus (ie + //an 8k buffer would have to start at an address which is a + //multiple of 8k. + // + //Now we could fix this for sure on the kernel side, by making + //sure we only commit correctly aligned memory into the chunk (as + //the pci driver itself does), + //However, by using a 4k chunk, we know this will be on a page + //boundary so the alignment is correct (assuming the page size + //isn't changed). + TInt testMapppedChunkSize = 0x1000; + test.Next(_L("Open and Close Pci Mappped Chunk\n")); + TestPciMapppedChunk(device,test,testMapppedChunkSize); + + test.Next(_L("Open and Close Pci Window Chunk\n")); + TestPciWindowChunk(device,test); + + const TInt numberOfThreads = info.iNumberOfBars; + test.Printf(_L("Open buffers concurrently, max supported = %d\n"), numberOfThreads); +#ifndef __VC32__ + TestBufferOpenConcurrency(device, test, numberOfThreads); +#else + test.Printf(_L("TestBufferOpenConcurrency not implemented for WINS"), numberOfThreads); +#endif + + test.Next(_L("Test loop back")); + TestLoopBack(device, test); + + device.Close(); + __KHEAP_MARKEND; + + r = User::FreeLogicalDevice(KPciLdd); + test_KErrNone(r); + + test.End(); + test.Close(); + + __UHEAP_MARKEND; + return KErrNone; + } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/pci/t_pci.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/pci/t_pci.h Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,254 @@ +// Copyright (c) 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: This is the header file for the PCI driver test , so far implemented +// only on the Naviengine platform + +#ifndef __TPCI_TEST_H +#define __TPCI_TEST_H + +#ifndef __KERNEL_MODE__ +#define __E32TEST_EXTENSION__ +#include + #include +#endif // __KERNEL_MODE__ + +_LIT(KPciLdd, "d_pci.ldd"); +_LIT(KPciLddFactory, "PCI_test_factory"); +_LIT(KPciTest, "PCI Test LDD"); + +/** +Test driver op-codes +*/ +enum TPciTestCmd + { + EGetTestInfo, + EAccessConfigSpace, + EAccessMemorySpace, + EOpenPciDChunk, + EOpenPciPlatHwChunk, + EOpenPciMappedChunk, + EOpenPciWindowChunk, + ERunUnitTests + }; + +/** +Identifies a PCI Function (device) on the system +*/ +struct TPciDevice + { + TPciDevice() + :iVendorId(0xFFFFFFFF), iDeviceId(0xFFFFFFFF), iInstance(0) {} + + TPciDevice(TUint aVendorId, TUint aDeviceId, TInt aInstance=0) + :iVendorId(aVendorId), iDeviceId(aDeviceId), iInstance(aInstance) {} + + TUint iVendorId; + TUint iDeviceId; + TInt iInstance; ///< Unit to open (there could be multiple devices on system) + }; + +/** +Used to send chunk size and recieve +PCI address +*/ +struct TPciChunkCreateInfo + { + TPciChunkCreateInfo() + :iSize(0), iPciAddress(NULL) + { + } + + TPciChunkCreateInfo(TInt aSize, TUint& aPciAddress, TRequestStatus* aStatus=NULL) + :iSize(aSize), iPciAddress(&aPciAddress), iStatus(aStatus) + { + } + TInt iSize; + TUint* iPciAddress; + TRequestStatus* iStatus; + }; + +/** +Information about the PSL required by the +user side test +*/ +struct TPciTestInfo + { + TPciDevice iDevice; ///< Probe for this + + /** + Supplies the necessary information to test Read, Write, and + Modify for a word of PCI memory or configuration space + */ + struct TAddrSpaceTest + { + TAddrSpaceTest() + :iOffset(0), iExpectedValue(0), iReadOnlyMask(0) + {} + + TAddrSpaceTest(TUint aOffset, TUint aExpectedValue, TUint aReadOnlyMask) + :iOffset(aOffset), iExpectedValue(aExpectedValue), iReadOnlyMask(aReadOnlyMask) + {} + + /** + Returns a specified sub byte, or word from the whole dword + */ + inline TUint Expected(TInt aBitWidth, TInt aExtraOffset) const + { + //the right shift required to get field to bit 0 + const TInt shift = 8 *((aExtraOffset + iOffset) % 4); + + const TUint mask = 0xFFFFFFFF >> (32-aBitWidth); + return (iExpectedValue >> shift) & mask; + } + + const TUint iOffset; + const TUint iExpectedValue; ///< The initial value of word + const TUint iReadOnlyMask; ///< Mask of unwritable bits + //Future work, memory spaces should state a bar index + }; + + + TAddrSpaceTest iCfgSpaceRead; + TAddrSpaceTest iCfgSpaceWrite; + + TUint iMemSpaceIndex; ///< Memory space to select + TAddrSpaceTest iMemSpaceRead; + TAddrSpaceTest iMemSpaceWrite; + + TInt iNumberOfBars; ///< Number of simultaneous mappings into PCI space + }; + +class RPci; +class TAddrSpace; +/** +This class encapsulates all the various read/write/and modify commands +that can be carried out on a PCI memory space. The command is stored user +side, and then executed on kernel side when KRun() is called. +*/ +class TUserPciSpace + { +public: + TUserPciSpace() + :iPci(NULL), iOperation(EInvalid), iBitWidth(0), iOffset(0), + iWriteValue(0), iClearMask(0), iSetMask(0) + {} + TUserPciSpace(RPci& aPci); + + /** + Perform the encapsulated read/write/or modify + @note Only run on kernel side + */ + TUint KRun(TAddrSpace& aAddrSpace); + + /** + Clone method is required so that multiple threads may + have their own copy of a TUserPciSpace (without knowing + its runtime type) + */ + virtual TUserPciSpace* Clone() const = 0; + + TUint Read(TInt aBitWidth, TUint aOffset) + { + iOffset = aOffset; + iOperation = ERead; + iBitWidth = aBitWidth; + + return Call(); + } + + void Write(TInt aBitWidth, TUint aOffset, TUint aValue) + { + iOffset = aOffset; + iOperation = EWrite; + iBitWidth = aBitWidth; + + iWriteValue = aValue; + Call(); + } + + void Modify(TInt aBitWidth, TUint aOffset, TUint aClearMask, TUint aSetMask) + { + iOffset = aOffset; + iOperation = EModify; + iBitWidth = aBitWidth; + + iClearMask = aClearMask; + iSetMask = aSetMask; + Call(); + } + +protected: + /** + Makes a request to iPci and passes a copy of this object to + the kernel side. + */ + virtual TUint Call() =0; + + enum TOperation {EInvalid, ERead, EWrite, EModify}; + + /** + Pointer to a PCI device handle + */ + RPci* iPci; + + TOperation iOperation; //!< Type of access to perform + TInt iBitWidth; + + TUint iOffset; + TUint32 iWriteValue; + TUint32 iClearMask; + TUint32 iSetMask; + }; + +/** +Grants access to a PCI device's (identified +by aPci) config space from user side +*/ +class TUserConfigSpace : public TUserPciSpace + { +public: + TUserConfigSpace() + :TUserPciSpace() + {} + TUserConfigSpace(RPci& aPci); + + virtual TUserPciSpace* Clone() const; +private: + TUint Call(); + }; + +/** +Grants access to some region of a PCI +device's memory space. A PCI device(or function) +may have up to 8 distinct memory spaces +*/ +class TUserMemorySpace : public TUserPciSpace + { +public: + TUserMemorySpace() + :TUserPciSpace(), iBarIndex(-1) + {} + + TUserMemorySpace(RPci& aPci, TInt aBarIndex); + + virtual TUserPciSpace* Clone() const; + + inline TInt BarIndex() {return iBarIndex;} + +private: + TUint Call(); + + TInt iBarIndex; ///< Each PCI function may have up to 8 memory spaces + }; + +#endif //__TPCI_TEST_H diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/resourceman/dynamicresource.cpp --- a/kerneltest/e32test/resourceman/dynamicresource.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/resourceman/dynamicresource.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -34,27 +34,21 @@ DMLIGLSSHNDynamicResource::DMLIGLSSHNDynamicResource() : DDynamicPowerResource(KDMLIGLSSHNDynamicResource, -5), iMinLevel(-5), iMaxLevel(-10), iCurrentLevel(-5) { iFlags = KMultiLevel | KLongLatencySet | KShared | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBLGLSSHNDynamicResource, "DynamicResource3"); DBLGLSSHNDynamicResource::DBLGLSSHNDynamicResource() : DDynamicPowerResource(KDBLGLSSHNDynamicResource, 1), iMinLevel(1), iMaxLevel(0), iCurrentLevel(1) { iFlags = KBinary | KLongLatencySet | KLongLatencyGet | KShared | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLLGLSSHPDynamicResource, "DynamicResource4"); DMLLGLSSHPDynamicResource::DMLLGLSSHPDynamicResource() : DDynamicPowerResource(KDMLLGLSSHPDynamicResource, 10), iMinLevel(10), iMaxLevel(20), iCurrentLevel(10) { iFlags = KMultiLevel | KLongLatencySet | KLongLatencyGet | KShared; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } //Constructors for dynamic dependent resources @@ -63,36 +57,28 @@ { // Make it a Instantaneous Resource. iFlags = KMultiLevel; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDDynamicResourceD02, "DynamicDependResourceDI"); DDynamicResourceD02::DDynamicResourceD02() : DDynamicPowerResourceD(KDDynamicResourceD02, 0), iMinLevel(0), iMaxLevel(1), iCurrentLevel(0) { iFlags = KBinary | KLongLatencySet | KLongLatencyGet | KShared; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDDynamicResourceD03, "DynamicDependResourceDJ"); DDynamicResourceD03::DDynamicResourceD03() : DDynamicPowerResourceD(KDDynamicResourceD03, 19), iMinLevel(19), iMaxLevel(9), iCurrentLevel(19) { iFlags = KMultiLevel | KLongLatencySet | KShared | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDDynamicResourceD04, "DynamicDependResourceDK"); DDynamicResourceD04::DDynamicResourceD04() : DDynamicPowerResourceD(KDDynamicResourceD04, 0), iMinLevel(0), iMaxLevel(1), iCurrentLevel(0) { iFlags = KBinary | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } //Get info implementation for dynamic resources diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/resourceman/resourceman_psl/rescontrol_extended_psl.cpp --- a/kerneltest/e32test/resourceman/resourceman_psl/rescontrol_extended_psl.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/resourceman/resourceman_psl/rescontrol_extended_psl.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -141,27 +141,21 @@ DMLSLGLSPDependResource::DMLSLGLSPDependResource() : DStaticPowerResourceD(KDMLSLGLSPDependResource, -100), iMinLevel(-100), iMaxLevel(100), iCurrentLevel(-100) { iFlags = KMultiLevel | KLongLatencyGet | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSIGLSNDependResource, "StaticDependResourceA"); DMLSIGLSNDependResource::DMLSIGLSNDependResource() : DStaticPowerResourceD(KDMLSIGLSNDependResource, -10), iMinLevel(-10), iMaxLevel(-20), iCurrentLevel(-10) { iFlags = KMultiLevel | KLongLatencySet | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSIGLSPDependResource, "StaticDependResourceF"); DBSIGLSPDependResource::DBSIGLSPDependResource() : DStaticPowerResourceD(KDBSIGLSPDependResource, 0), iMinLevel(0), iMaxLevel(1), iCurrentLevel(0) { iFlags = KBinary | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHIGLSPDependResource, "StaticDependResourceE"); @@ -169,36 +163,28 @@ { // Make it a Instantaneous Resource. iFlags = KMultiLevel | KShared; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSHLGLSNDependResource, "StaticDependResourceC"); DBSHLGLSNDependResource::DBSHLGLSNDependResource() : DStaticPowerResourceD(KDBSHLGLSNDependResource, 1), iMinLevel(1), iMaxLevel(0), iCurrentLevel(1) { iFlags = KBinary | KLongLatencyGet | KLongLatencySet | KShared | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHLGLSNDependResource, "StaticDependResourceG"); DMLSHLGLSNDependResource::DMLSHLGLSNDependResource() : DStaticPowerResourceD(KDMLSHLGLSNDependResource, 75), iMinLevel(75), iMaxLevel(30), iCurrentLevel(75) { iFlags = KMultiLevel | KLongLatencyGet | KLongLatencySet | KShared | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHLGLSCDependResource, "DMLSHLGLSCDependResource"); DMLSHLGLSCDependResource::DMLSHLGLSCDependResource() : DStaticPowerResourceD(KDMLSHLGLSCDependResource, -100), iMinLevel(-100), iMaxLevel(100), iCurrentLevel(-100) { iFlags = KMultiLevel; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } //Implementation of handle dependent state for all resources diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/resourceman/resourceman_psl/rescontrol_psl.cpp --- a/kerneltest/e32test/resourceman/resourceman_psl/rescontrol_psl.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/resourceman/resourceman_psl/rescontrol_psl.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -456,45 +456,35 @@ DMLSLGLSPResource::DMLSLGLSPResource() : DStaticPowerResource(KDMLSLGLSPResource, 75), iMinLevel(10), iMaxLevel(75), iCurrentLevel(75), iPolled(EFalse) { iFlags = KMultiLevel | KLongLatencySet | KLongLatencyGet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSLGISNResource, "DBSLGISNResource"); DBSLGISNResource::DBSLGISNResource() : DStaticPowerResource(KDBSLGISNResource, E_ON), iMinLevel(E_ON), iMaxLevel(E_OFF), iCurrentLevel(E_ON), iPolled(ETrue) { iFlags = KLongLatencyGet | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSLGISNResource, "DMLSLGISNResource"); DMLSLGISNResource::DMLSLGISNResource() : DStaticPowerResource(KDMLSLGISNResource, 75), iMinLevel(75), iMaxLevel(10), iCurrentLevel(75), iPolled(EFalse) { iFlags = KMultiLevel | KLongLatencyGet | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSIGLSPResource, "DBSIGLSPResource"); DBSIGLSPResource::DBSIGLSPResource() : DStaticPowerResource(KDBSIGLSPResource, E_ON), iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(ETrue) { iFlags = KBinary | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSIGLSPResource, "DMLSIGLSPResource"); DMLSIGLSPResource::DMLSIGLSPResource() : DStaticPowerResource(KDMLSIGLSPResource, 75), iMinLevel(10), iMaxLevel(100), iCurrentLevel(75), iPolled(EFalse) { iFlags = KMultiLevel | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSHIGISPResource, "DBSHIGISPResource"); @@ -525,54 +515,42 @@ DBSHLGLSPResource::DBSHLGLSPResource() : DStaticPowerResource(KDBSHLGLSPResource, E_ON), iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(ETrue) { iFlags = KBinary | KShared | KLongLatencySet | KLongLatencyGet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHLGLSPResource, "DMLSHLGLSPResource"); DMLSHLGLSPResource::DMLSHLGLSPResource() : DStaticPowerResource(KDMLSHLGLSPResource, 70), iMinLevel(5), iMaxLevel(70), iCurrentLevel(70), iPolled(EFalse) { iFlags = KMultiLevel | KShared | KLongLatencySet | KLongLatencyGet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSHLGISNResource, "DBSHLGISNResource"); DBSHLGISNResource::DBSHLGISNResource() : DStaticPowerResource(KDBSHLGISNResource, E_ON), iMinLevel(E_ON), iMaxLevel(E_OFF), iCurrentLevel(E_ON), iPolled(ETrue) { iFlags = KBinary | KShared | KLongLatencyGet | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHLGISNResource, "DMLSHLGISNResource"); DMLSHLGISNResource::DMLSHLGISNResource() : DStaticPowerResource(KDMLSHLGISNResource, 75), iMinLevel(75), iMaxLevel(10), iCurrentLevel(75), iPolled(EFalse) { iFlags = KMultiLevel | KShared | KLongLatencySet | KSenseNegative; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSHIGLSPResource, "DBSHIGLSPResource"); DBSHIGLSPResource::DBSHIGLSPResource() : DStaticPowerResource(KDBSHIGLSPResource, E_ON), iMinLevel(E_OFF), iMaxLevel(E_ON), iCurrentLevel(E_ON), iPolled(ETrue) { iFlags = KBinary | KShared | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDMLSHIGLSPResource, "DMLSHIGLSPResource"); DMLSHIGLSPResource::DMLSHIGLSPResource() : DStaticPowerResource(KDMLSHIGLSPResource, 75), iMinLevel(10), iMaxLevel(75), iCurrentLevel(75), iPolled(EFalse) { iFlags = KMultiLevel | KShared | KLongLatencySet; - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } _LIT(KDBSHLGLSCResource, "KDBSHLGLSCResource"); @@ -580,9 +558,7 @@ { iFlags = KMultiLevel | KShared | KLongLatencySet | KSenseCustom; SetCustomFunction(CustomFunction); - NKern::LockSystem(); iBlockTime = MIN_BLOCK_TIME + Kern::Random() % MAX_BLOCK_TIME; - NKern::UnlockSystem(); } //DoRequest implementation of all functions diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/system/d_dobject.cpp --- a/kerneltest/e32test/system/d_dobject.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/system/d_dobject.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -665,10 +665,10 @@ // Bit 30 thread local flag (ignored) // Bit 31 special handle flag (should be 0) // - NKern::LockSystem(); TInt randomHandle = Kern::Random() & 0x3fff7fff; TInt uniqueID = 0; // any object type! - + + NKern::LockSystem(); object = myIx.At(randomHandle, uniqueID); NKern::UnlockSystem(); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/usb/t_usb_device/include/activecontrol.h --- a/kerneltest/e32test/usb/t_usb_device/include/activecontrol.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/usb/t_usb_device/include/activecontrol.h Sat Feb 20 00:10:51 2010 +0200 @@ -80,7 +80,10 @@ TInt ReEnumerate(); TInt ProcessEp0ControlPacket(); void PrintHostLog(); - + + void FillEndpointsResourceAllocation(IFConfigPtr aIfCfg); + void PopulateInterfaceResourceAllocation(IFConfigPtr aFirstIfCfg, TInt aPortNumber); + private: CConsoleBase* iConsole; // a console to read from CActiveStallNotifier* iStallNotifier[KMaxInterfaces]; @@ -91,6 +94,7 @@ TInt iNumInterfaceSettings[KMaxInterfaces]; TInt iTotalChannels; TBool iSoftwareConnect; + TBool iSupportResourceAllocationV2; TBool iHighSpeed; RFs iFs; RFile iConfigFile; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/usb/t_usb_device/src/activecontrol.cpp --- a/kerneltest/e32test/usb/t_usb_device/src/activecontrol.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/usb/t_usb_device/src/activecontrol.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -127,6 +127,7 @@ : CActive(EPriorityNormal), iConsole(aConsole), iSoftwareConnect(EFalse), + iSupportResourceAllocationV2(EFalse), iHighSpeed(EFalse), iConfigFileName(aConfigFile), iScriptFileName(aScriptFile), @@ -219,7 +220,12 @@ } test_NotNull(ifPtr); - + + if (iSupportResourceAllocationV2) + { + PopulateInterfaceResourceAllocation(ifPtr, portNumber); + } + IFConfigPtr defaultIfPtr = ifPtr; SetupInterface(&ifPtr,portNumber); @@ -228,15 +234,17 @@ test_KErrNone(iPort[portNumber].FinalizeInterface(tChunk)); #endif - // allocate endpoint DMA and double buffering for all endpoints on default interface - for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + if (!iSupportResourceAllocationV2) { - defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); - #ifndef USB_SC - defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); - #endif - } - + // allocate endpoint DMA and double buffering for all endpoints on default interface when using resource allocation v1 api + for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); + #ifndef USB_SC + defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); + #endif + } + } } iTotalChannels += lddPtr->iNumChannels; @@ -369,14 +377,17 @@ RChunk *tChunk = &gChunk; test_KErrNone(iPort[portNumber].FinalizeInterface(tChunk)); #endif - - // allocate endpoint DMA and double buffering for all endpoints on default interface - for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + + if (!iSupportResourceAllocationV2) { - defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); - #ifndef USB_SC - defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); - #endif + // allocate endpoint DMA and double buffering for all endpoints on default interface with resource allocation v1 api + for (TUint8 i = 1; i <= defaultIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + defaultIfPtr->iEpDMA[i-1] ? AllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateEndpointDMA(&iPort[portNumber],(TENDPOINTNUMBER)i); + #ifndef USB_SC + defaultIfPtr->iEpDoubleBuff[i-1] ? AllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i) : DeAllocateDoubleBuffering(&iPort[portNumber],(TENDPOINTNUMBER)i); + #endif + } } } @@ -422,6 +433,59 @@ test.End(); } + +void CActiveControl::FillEndpointsResourceAllocation(IFConfigPtr aIfCfg) + { + + #ifdef USB_SC + TUsbcScInterfaceInfo* iInfoPtr = aIfCfg->iInfoPtr; + #else + TUsbcInterfaceInfo* iInfoPtr = aIfCfg->iInfoPtr; + #endif + + // fill resource allocation info in the endpoint info with resource allocation v2 + for (TUint8 i = 1; i <= iInfoPtr->iTotalEndpointsUsed; i++) + { + if (aIfCfg->iEpDMA[i-1]) + { + iInfoPtr->iEndpointData[i-1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DMA; + } + else + { + iInfoPtr->iEndpointData[i-1].iFeatureWord1 &= (~KUsbcEndpointInfoFeatureWord1_DMA); + } + #ifndef USB_SC + if (aIfCfg->iEpDoubleBuff[i-1]) + { + iInfoPtr->iEndpointData[i-1].iFeatureWord1 |= KUsbcEndpointInfoFeatureWord1_DoubleBuffering; + } + else + { + iInfoPtr->iEndpointData[i-1].iFeatureWord1 &= (~KUsbcEndpointInfoFeatureWord1_DoubleBuffering); + } + #endif + } + } + +// all alternative settings of the interface 'aFirstIfCfg' will be populated +void CActiveControl::PopulateInterfaceResourceAllocation(IFConfigPtr aFirstIfCfg, TInt aPortNumber) + { + FillEndpointsResourceAllocation(aFirstIfCfg); + + IFConfigPtr ifCfgPtr = aFirstIfCfg->iPtrNext; + while (ifCfgPtr != NULL) + { + if (ifCfgPtr->iAlternateSetting) + { + FillEndpointsResourceAllocation(ifCfgPtr); + ifCfgPtr = ifCfgPtr->iPtrNext; + } + else + { + ifCfgPtr = NULL; + } + } + } void CActiveControl::SetupInterface(IFConfigPtr* aIfPtr, TInt aPortNumber) { @@ -1397,11 +1461,16 @@ TUSB_PRINT1("Supports unpowered cable detection: %s\n", (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ? _S("yes") : _S("no")); + TUSB_PRINT1("Supports endpoint resource allocation v2 scheme: %s\n", + (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ? + _S("yes") : _S("no")); TUSB_PRINT(""); iSoftwareConnect = d_caps().iConnect; // we need to remember this test_Equal(aLddPtr->iSoftConnect,iSoftwareConnect); + iSupportResourceAllocationV2 = ((d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0); + // only check capabilities if set; therefore allowing them to be disabled if (aLddPtr->iSelfPower) { diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/usb/t_usb_device/src/activedevicestatenotifier.cpp --- a/kerneltest/e32test/usb/t_usb_device/src/activedevicestatenotifier.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/usb/t_usb_device/src/activedevicestatenotifier.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -114,28 +114,35 @@ TUint8 altSetting = iDeviceState & ~KUsbAlternateSetting; TUSB_PRINT2("Device State notifier: Alternate interface %d setting has changed: now %d", iPortNumber, altSetting); - - // allocate endpoint DMA and double buffering for all endpoints on interface - for (TUint8 ifNumber = 0; ifNumber < 128; ifNumber++) + + TUsbDeviceCaps dCaps; + iPort->DeviceCaps(dCaps); + TBool isResourceAllocationV2 = ((dCaps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) != 0); + if (!isResourceAllocationV2) { - IFConfigPtr newIfPtr = gInterfaceConfig[ifNumber][altSetting]; - if (newIfPtr) + // allocate endpoint DMA and double buffering for all endpoints on interface for resource allocation v1 + // if resource allocation v2, refer to CActiveControl::ConstructL and CActiveControl::PopulateInterfaceResourceAllocation + for (TUint8 ifNumber = 0; ifNumber < 128; ifNumber++) { - if (newIfPtr->iPortNumber == iPortNumber) + IFConfigPtr newIfPtr = gInterfaceConfig[ifNumber][altSetting]; + if (newIfPtr) { - // allocate endpoint DMA and double buffering for all endpoints on default interface - for (TUint8 i = 1; i <= newIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + if (newIfPtr->iPortNumber == iPortNumber) { - newIfPtr->iEpDMA[i-1] ? gActiveControl->AllocateEndpointDMA(iPort,(TENDPOINTNUMBER)i) : gActiveControl->DeAllocateEndpointDMA(iPort,(TENDPOINTNUMBER)i); - #ifndef USB_SC - newIfPtr->iEpDoubleBuff[i-1] ? gActiveControl->AllocateDoubleBuffering(iPort,(TENDPOINTNUMBER)i) : gActiveControl->DeAllocateDoubleBuffering(iPort,(TENDPOINTNUMBER)i); - #endif + // allocate endpoint DMA and double buffering for all endpoints on default interface + for (TUint8 i = 1; i <= newIfPtr->iInfoPtr->iTotalEndpointsUsed; i++) + { + newIfPtr->iEpDMA[i-1] ? gActiveControl->AllocateEndpointDMA(iPort,(TENDPOINTNUMBER)i) : gActiveControl->DeAllocateEndpointDMA(iPort,(TENDPOINTNUMBER)i); + #ifndef USB_SC + newIfPtr->iEpDoubleBuff[i-1] ? gActiveControl->AllocateDoubleBuffering(iPort,(TENDPOINTNUMBER)i) : gActiveControl->DeAllocateDoubleBuffering(iPort,(TENDPOINTNUMBER)i); + #endif + } + break; } - break; } } - } - + } + if (gAltSettingOnNotify) { for (TUint16 i =0; i < KMaxConcurrentTests; i++) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/usbho/t_usbdi/inc/PBASE-T_USBDI-1231.h --- a/kerneltest/e32test/usbho/t_usbdi/inc/PBASE-T_USBDI-1231.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/usbho/t_usbdi/inc/PBASE-T_USBDI-1231.h Sat Feb 20 00:10:51 2010 +0200 @@ -130,7 +130,10 @@ TCaseSteps iCaseStep; TThreadPriority iPriority; - + +public: + TBool iInterface0Resumed; + private: /** The functor for this test case for the factory diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32test/usbho/t_usbdi/src/PBASE-T_USBDI-1231.cpp --- a/kerneltest/e32test/usbho/t_usbdi/src/PBASE-T_USBDI-1231.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/usbho/t_usbdi/src/PBASE-T_USBDI-1231.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -40,7 +40,7 @@ } CUT_PBASE_T_USBDI_1231::CUT_PBASE_T_USBDI_1231(TBool aHostRole) : - CBaseTestCase(KTestCaseId, aHostRole) + CBaseTestCase(KTestCaseId, aHostRole), iInterface0Resumed(EFalse) { } @@ -148,7 +148,9 @@ LOG_FUNC RDebug::Printf("====> DeviceInsertedL entry priority = %d", RThread().Priority()); - + + iInterface0Resumed = EFalse; + Cancel(); // Cancel the timer TInt err(KErrNone); iDeviceHandle = aDeviceHandle; @@ -244,6 +246,7 @@ TInt testStep = self->iCaseStep; RDebug::Printf(" -watcher 0 iStatus = %d ",completionCode, testStep); + self->iInterface0Resumed = ETrue; switch (self->iCaseStep) { @@ -339,8 +342,15 @@ if (aNewState == RUsbDevice::EDeviceActive) { RDebug::Printf("Device resume!"); - iCaseStep = EValidResumeWhenSuspending; - + if (!iInterface0Resumed) + { + iCaseStep = EValidResumeWhenSuspending; + } + else + { + iCaseStep = EPassed; + SendEp0Request(); + } } else { diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32utils/group/bld.inf --- a/kerneltest/e32utils/group/bld.inf Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32utils/group/bld.inf Sat Feb 20 00:10:51 2010 +0200 @@ -53,6 +53,9 @@ btrace_host #endif +//Nist statistical test suite for Secure RNG in kernel +nistsecurerng + PRJ_MMPFILES #if defined(TOOLS2) @@ -99,7 +102,6 @@ #ifndef SMP ../d_exc/d_exc -../sdpartition/sdpartition #endif ../d_exc/minkda @@ -115,3 +117,4 @@ #endif // !TOOLS + diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/e32utils/group/nistsecurerng.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32utils/group/nistsecurerng.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -0,0 +1,62 @@ +// Copyright (c) 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: +// + +TARGET nistsecurerng.exe +TARGETTYPE exe +UID 0x20027F9A + +USERINCLUDE ../nistsecurerng/include +USERINCLUDE ../nistsecurerng/include/utils + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + +SOURCEPATH ../nistsecurerng/src +SOURCE assess.cpp +SOURCE approximateEntropy.cpp +SOURCE blockFrequency.cpp +SOURCE cephes.cpp +SOURCE cusum.cpp +SOURCE discreteFourierTransform.cpp +SOURCE dfft.cpp +SOURCE frequency.cpp +SOURCE generators.cpp +SOURCE genutils.cpp +SOURCE linearComplexity.cpp +SOURCE longestRunOfOnes.cpp +SOURCE matrix.cpp +SOURCE nonOverlappingTemplateMatchings.cpp +SOURCE overlappingTemplateMatchings.cpp +SOURCE randomExcursions.cpp +SOURCE randomExcursionsVariant.cpp +SOURCE rank.cpp +SOURCE runs.cpp +SOURCE serial.cpp +SOURCE universal.cpp +SOURCE utilities.cpp +//provides some openc c functions that are not avaiable in kernel + +SOURCEPATH ../nistsecurerng/src/utils +SOURCE openc.cpp +SOURCE qsort.cpp + +SOURCEPATH ../nistsecurerng/src/math +SOURCE erf.cpp + + +LIBRARY euser.lib efsrv.lib + +EPOCHEAPSIZE 0x0800000 0x8000000 + +SMPSAFE diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/demandpaging/t_wdpstress.cpp --- a/kerneltest/f32test/demandpaging/t_wdpstress.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/demandpaging/t_wdpstress.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1793,7 +1793,10 @@ //infoPtrs[index]->SetUseHeap(gThreadHeap); ret = pTheThreads[index].Create(*infoPtrs[index]); if (ret != KErrNone) + { + pThreadInUse[index] = 0; continue; + } pTheThreads[index].Resume(); pThreadInUse[index] = 1; continue; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/fileshare/handshare.cpp --- a/kerneltest/f32test/fileshare/handshare.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/fileshare/handshare.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -648,7 +648,7 @@ TInt end_thc, end_phc; RThread().HandleCount(end_phc, end_thc); test(start_thc == end_thc); - test(start_phc == end_phc); +// test(start_phc == end_phc); // and also for pending requests ... test(RThread().RequestCount() == 0); @@ -699,7 +699,7 @@ // wait for server2's thread to end gracefully User::WaitForRequest(statq); - + test(statq == KErrNone); server2Thread.Close(); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/filesystem/automounter/t_automounter.mmp --- a/kerneltest/f32test/filesystem/automounter/t_automounter.mmp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/filesystem/automounter/t_automounter.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -25,7 +25,9 @@ SOURCE fat_utils.cpp f32_test_utils.cpp LIBRARY euser.lib efsrv.lib hal.lib -SYSTEMINCLUDE /epoc32/include + +OS_LAYER_SYSTEMINCLUDE_SYMBIAN + USERINCLUDE ../../fileutils/inc USERINCLUDE ../fat diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/group/b_gen.mmp --- a/kerneltest/f32test/group/b_gen.mmp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/group/b_gen.mmp Sat Feb 20 00:10:51 2010 +0200 @@ -22,8 +22,11 @@ SOURCE t_main.cpp SOURCEPATH ../fileutils/src SOURCE t_chlffs.cpp +SOURCE f32_test_utils.cpp + LIBRARY euser.lib efsrv.lib hal.lib OS_LAYER_SYSTEMINCLUDE_SYMBIAN + USERINCLUDE ../server USERINCLUDE ../fileutils/inc diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/server/b_gen.cpp --- a/kerneltest/f32test/server/b_gen.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/server/b_gen.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -20,12 +20,10 @@ #include "t_server.h" #include "t_chlffs.h" -#ifdef __VC32__ - // Solve compilation problem caused by non-English locale - #pragma setlocale("english") -#endif +#include "f32_test_utils.h" +using namespace F32_Test_Utils; -GLDEF_D RTest test(_L("B_GEN")); +RTest test(_L("B_GEN")); // // File test - general test of local filing system routines // (finishes with formating current device). @@ -37,67 +35,64 @@ // GLREF_D P_DEVICE p_file; // GLREF_D P_DEVICE p_wind,p_screen,p_cons; -GLDEF_D TBuf<0x100> gNameBuf; -GLDEF_D TBuf<0x100> gNameOut; -GLDEF_D RFile gFile; -GLDEF_D RFile gFileErr; -GLDEF_D RFile gFile2; -GLDEF_D RDir gDir; -GLDEF_D RFormat gFormat; -//GLDEF_D void *chan1,*chan2; -GLDEF_D TFileName fBuf; -//GLDEF_D TUint8 fBuf[P_FNAMESIZE]; +TBuf<0x100> gNameBuf; +TBuf<0x100> gNameOut; +RFile gFile; +RFile gFileErr; +RFile gFile2; +RDir gDir; +RFormat gFormat; +TFileName fBuf; +TInt gDriveNum = -1; -LOCAL_D TBuf8<0x4000> gDataBuf; -LOCAL_D TEntry gFileEntry; -// LOCAL_D P_DINFO volInfo; -LOCAL_D TVolumeInfo volInfo; -// LOCAL_D P_NINFO nInfo; -LOCAL_D TFileName pathBuf; +static TBuf8<0x4000> gDataBuf; +static TEntry gFileEntry; +static TVolumeInfo volInfo; +static TFileName pathBuf; -LOCAL_D TInt NameErr=KErrBadName; -LOCAL_D TInt DirErr=KErrPathNotFound; -LOCAL_D TInt AccessErr=KErrAccessDenied; -LOCAL_D TInt LockedErr=KErrInUse; -LOCAL_D TInt ExistsErr=KErrAlreadyExists; -LOCAL_D TInt NotExistsErr=KErrNotFound; -LOCAL_D TInt EofErr=KErrEof; -LOCAL_D TInt DeviceErr=KErrNotReady; +const TInt NameErr=KErrBadName; +const TInt DirErr=KErrPathNotFound; +const TInt AccessErr=KErrAccessDenied; +const TInt LockedErr=KErrInUse; +const TInt ExistsErr=KErrAlreadyExists; +const TInt NotExistsErr=KErrNotFound; +const TInt EofErr=KErrEof; +const TInt DeviceErr=KErrNotReady; //LOCAL_D TInt NoFileSystemErr=KErrNotReady; //LOCAL_D TInt NotSupportedErr=KErrNotSupported; -LOCAL_D TInt ReadOnlyErr=KErrAccessDenied; +const TInt ReadOnlyErr=KErrAccessDenied; -LOCAL_D TInt P_FASTREAM=EFileStream; -LOCAL_D TInt P_FAEXEC=0; -LOCAL_D TInt P_FAMOD=KEntryAttArchive; -LOCAL_D TInt P_FAREAD=KEntryAttReadOnly; +const TInt P_FASTREAM=EFileStream; +const TInt P_FAEXEC=0; +const TInt P_FAMOD=KEntryAttArchive; +const TInt P_FAREAD=KEntryAttReadOnly; //LOCAL_D TInt P_FAHIDDEN=KEntryAttHidden; //LOCAL_D TInt P_FASYSTEM=KEntryAttSystem; -//LOCAL_C TInt P_FAVOLUME=KEntryAttVolume; -LOCAL_C TInt P_FADIR=KEntryAttDir; -LOCAL_C TInt P_FRANDOM=0; -LOCAL_C TInt P_FABS=ESeekStart; +//static TInt P_FAVOLUME=KEntryAttVolume; +const TInt P_FADIR=KEntryAttDir; +const TInt P_FRANDOM=0; +const TInt P_FABS=ESeekStart; -LOCAL_C TInt P_FUPDATE=EFileWrite; +const TInt P_FUPDATE=EFileWrite; -LOCAL_C void doError(const TDesC &aMess, TInt anErr, TInt line) +static void doError(const TDesC &aMess, TInt anErr, TInt line) { test.Printf(_L("%S failed at line %d. Error %d\n"),&aMess, line, anErr); test(0); } #define Error(aMess, anErr) doError(aMess, anErr, __LINE__) -LOCAL_C void doError2(const TDesC &aMess, TInt anErr, TInt line, TInt callLine) +static void doError2(const TDesC &aMess, TInt anErr, TInt line, TInt callLine) { test.Printf(_L("%S failed at line %d. Error %d. Called from line %d\n"),&aMess, line, anErr, callLine); \ test(0); } #define Error2(aMess, anErr, line) doError2(aMess, anErr, __LINE__, line) -LOCAL_C void testWrite(const TDesC& aName,TInt aLen,TInt32 aSize,TBool aShouldChange) +static void testWrite(const TDesC& aName,TInt aLen,TInt32 aSize,TBool aShouldChange) // // Write to a file // @@ -123,7 +118,7 @@ Error(_L("Size check 602"),0); } -LOCAL_C void testSetEof(const TDesC& aName,TUint32 aPos,TBool aShouldChange) +static void testSetEof(const TDesC& aName,TUint32 aPos,TBool aShouldChange) // // Set the end of a file // @@ -148,7 +143,7 @@ } -LOCAL_C void testDir(const TDesC& aDirName) +static void testDir(const TDesC& aDirName) // // Create a directory // @@ -173,7 +168,7 @@ /* -LOCAL_C void testNodeInfo(const TDesC& aName,TInt type,TInt anErr) +static void testNodeInfo(const TDesC& aName,TInt type,TInt anErr) // // Test p_ninfo. // @@ -193,7 +188,7 @@ } */ -LOCAL_C void testDeviceInfo(const TDesC& aDeviceName,TInt anErr) +static void testDeviceInfo(const TDesC& aDeviceName,TInt anErr) // // Test p_dinfo. // @@ -218,7 +213,7 @@ } } -LOCAL_C void testFileInfo(const TDesC& aFileName,TInt anErr) +static void testFileInfo(const TDesC& aFileName,TInt anErr) // // Test entry info // @@ -247,7 +242,7 @@ } } -LOCAL_C void testRenameFromRoot(const TDesC& aRName,const TDesC& aDName) +static void testRenameFromRoot(const TDesC& aRName,const TDesC& aDName) // // // @@ -263,7 +258,7 @@ Error(_L("Delete 92"),c); } -LOCAL_C void testRenameToRoot(const TDesC& pName,const TDesC& rName) +static void testRenameToRoot(const TDesC& pName,const TDesC& rName) // // // @@ -282,7 +277,7 @@ Error(_L("Delete 91"),c); } -LOCAL_C void verifyTestPat1() +static void verifyTestPat1() // // // @@ -320,7 +315,7 @@ test(err == KErrNone); } -LOCAL_C void testRename() +static void testRename() // // Test TheFs.Rename function. // @@ -475,7 +470,7 @@ TestINC103141(); // PDEF104017 } -LOCAL_C void testDelete() +static void testDelete() // // Test RFs::Delete function. // @@ -501,7 +496,7 @@ Error(_L("Delete 504"),c); } -LOCAL_C void testUnique(TUint fileFormat) +static void testUnique(TUint fileFormat) // // Test RFile::Temp // @@ -525,7 +520,7 @@ Error(_L("Delete"),c); } -LOCAL_C void testFileName(const TDesC& aFileName,TInt res) +static void testFileName(const TDesC& aFileName,TInt res) // // // @@ -556,8 +551,7 @@ } } -#if defined(_UNICODE) -LOCAL_C void testFileName(const TDesC8& aFileName,TInt res) +static void testFileName(const TDesC8& aFileName,TInt res) // // Defined to cope with all the instances of testFileName(gDataBuf,...) // @@ -565,9 +559,8 @@ TPtrC gDataBuf16((TText*)aFileName.Ptr(),gDataBuf.Size()/sizeof(TText8)); testFileName(gDataBuf16,res); } -#endif -LOCAL_C void testVolumeName(const TDesC& aVolumeName,TInt aResultExpected) +static void testVolumeName(const TDesC& aVolumeName,TInt aResultExpected) // // // @@ -605,7 +598,7 @@ } #define testMakeDir(aDirName, res) TestMakeDirLine(aDirName, res, __LINE__) -LOCAL_C void TestMakeDirLine(const TDesC& aDirName,TInt res, TInt line) +static void TestMakeDirLine(const TDesC& aDirName,TInt res, TInt line) // // // @@ -663,8 +656,8 @@ } } -#if defined(_UNICODE) -LOCAL_C void TestMakeDirLine(const TDesC8& aDirName, TInt res, TInt line) + +static void TestMakeDirLine(const TDesC8& aDirName, TInt res, TInt line) // // Defined to cope with all the instances of testMakeDir(gDataBuf,...) // @@ -674,10 +667,10 @@ // Not sizeof(TText16) since gDataBuf is a TBuf*! TestMakeDirLine(gDataBuf16, res, line); } -#endif + #ifdef TEST_MEDIA -LOCAL_C void testMedia(const TDesC& instructions,TInt anErr) +static void testMedia(const TDesC& instructions,TInt anErr) // // // @@ -713,11 +706,25 @@ } #endif -GLDEF_C void CallTestsL() -// -// Do All tests -// +void CallTestsL() { + + //-- set up console output + F32_Test_Utils::SetConsole(test.Console()); + + TInt nRes=TheFs.CharToDrive(gDriveToTest, gDriveNum); + test(nRes==KErrNone); + + PrintDrvInfo(TheFs, gDriveNum); + + //-- quick format the drive, if it isn't the emulator's C: + if(!Is_Win32(TheFs, gDriveNum)) + { + nRes = FormatDrive(TheFs, gDriveNum, ETrue); + test(nRes==KErrNone); + } + + //----------------------------------- TInt c; TInt i,count; TInt pos; @@ -1452,37 +1459,15 @@ if (c==LockedErr || c==AccessErr) { test.Printf(_L("Format: locked, no test\n")); - goto noFormat; } + else + { Error(_L("Format lock check"),c); } + } -// if ((c=p_read(chan2,&count,2))<0) -// { -// if (c==NotSupportedErr) -// { -// test.Printf(_L("Format: not supported, no test\n")); -// goto noFormatClose; -// } -// Error(_L("Read format count"),c); -// } -// for (i=1;;i++) -// { -// if ((c=g(chan2,&val,2))<0) -// { -// if (c==EofErr) -// break; -// Error(_L("Format"),c); -// } -// test.Printf(_L("\r%05u %05u\n"),i,val); -// } -// if ((i-1)!=count) -// Error(_L("Format count"),i); -// noFormatClose: -// if ((c=p_close(chan2))!=KErrNone) -// Error(_L("Close"),c); -noFormat: gFormat.Close(); + DeleteTestDirectory(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/server/t_falsespace.cpp --- a/kerneltest/f32test/server/t_falsespace.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/server/t_falsespace.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1062,13 +1062,6 @@ { //-- set up console output Fat_Test_Utils::SetConsole(test.Console()); - - - if (gSessionPath[0]=='C') //only test on non C drives - { - test.Printf(_L("TEST NOT RUN FOR THIS DRIVE")); - return; - } if (UserSvr::DebugMask(2)&0x00000002) // TESTFAST mode set? (for automated test builds) if(IsTestingLFFS()) @@ -1086,6 +1079,23 @@ r=RFs::DriveToChar(gTestDrive,gCh); test(r==KErrNone); + TDriveInfo drv; + r = TheFs.Drive(drv, gTestDrive); + test(r == KErrNone); + + if (Is_Win32(TheFs, gTestDrive)) + { + test.Printf(_L("Skipping on emulator %C: drive\n"), gSessionPath[0]); + return; + } + + // do not run this test on RAM drive + if (drv.iType == EMediaRam) + { + test.Printf(_L("Test can't run on RAM drive %C:\n"), gSessionPath[0]); + return; + } + //-- print drive information PrintDrvInfo(TheFs, gTestDrive); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/server/t_locate.cpp --- a/kerneltest/f32test/server/t_locate.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/server/t_locate.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -162,7 +162,7 @@ err = TheFs.Drive(info, i); test( err == KErrNone ); - if( info.iDriveAtt & KDriveAttRemovable ) + if(( info.iDriveAtt & KDriveAttRemovable ) && !( info.iDriveAtt & KDriveAttLogicallyRemovable )) { if ( ( info.iType != EMediaNotPresent) && (info.iType != EMediaUnknown) && (info.iType != EMediaCdRom) ) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/server/t_main.cpp --- a/kerneltest/f32test/server/t_main.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/server/t_main.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -662,12 +662,24 @@ test.Printf(_L("DriveCacheFlags = %08X\n"), gDriveCacheFlags); #if defined(_DEBUG) || defined(_DEBUG_RELEASE) + test.Printf(_L("\n")); + + TInt orgSessionCount; + r = controlIo(TheFs,theDrive, KControlIoSessionCount, orgSessionCount); + test(r==KErrNone); + test.Printf(_L("Session count start=%d\n"),orgSessionCount); + + TInt orgObjectCount; + r = controlIo(TheFs,theDrive, KControlIoObjectCount, orgObjectCount); + test(r==KErrNone); + test.Printf(_L("Object count start=%d\n"),orgObjectCount); + + TPckgBuf pkgOrgValues; TIOCacheValues& orgValues=pkgOrgValues(); r = controlIo(TheFs,theDrive, KControlIoCacheCount, orgValues); test_KErrNone(r); - test.Printf(_L("\n")); test.Printf(_L("Requests on close queue at start=%d\n"),orgValues.iCloseCount); test.Printf(_L("Requests on free queue at start=%d\n"),orgValues.iFreeCount); test.Printf(_L("Requests dynamically allocated at start=%d\n"),orgValues.iAllocated); @@ -702,6 +714,80 @@ TheFs.SetAllocFailure(gAllocFailOff); #if defined(_DEBUG) || defined(_DEBUG_RELEASE) + // Close and then re-open the main file server session to force the closure of + // any sub-sessions which may have been left open.... + // NB: This won't help if the test has opened another session & left sub-sessions open. + TheFs.Close(); + r=TheFs.Connect(); + test(r==KErrNone); + + // Display the file cache stats before closing the file queue + TFileCacheStats endFileCacheStats; + r = controlIo(TheFs,theDrive, KControlIoFileCacheStats, endFileCacheStats); + test_Value(r, r == KErrNone || r == KErrNotSupported); + test.Printf(_L("File cache: Cachelines (free %d, used %d), Segments(allocated %d locked %d). Closed files(%d)\n"), + endFileCacheStats.iFreeCount, + endFileCacheStats.iUsedCount, + endFileCacheStats.iAllocatedSegmentCount, + endFileCacheStats.iLockedSegmentCount, + endFileCacheStats.iFilesOnClosedQueue); + + + // Wait up to 3 seconds for all file server sessions & objects to close + // and then test session & object counts haven't changed + TInt endSessionCount = 0; + TInt endObjectCount = 0; + for (TInt n=0; n<3; n++) + { + // Flush the closed files queue as a file-cache object on the closed queue is counted as an open object + test.Printf(_L("Flushing close queue...\n")); + r = TheFs.ControlIo(theDrive, KControlIoFlushClosedFiles); + test_KErrNone(r); + + r = controlIo(TheFs,theDrive, KControlIoSessionCount, endSessionCount); + test(r==KErrNone); + test.Printf(_L("Session count end=%d\n"),endSessionCount); + + r = controlIo(TheFs,theDrive, KControlIoObjectCount, endObjectCount); + test(r==KErrNone); + test.Printf(_L("Object count end=%d\n"),endObjectCount); + + if (endSessionCount == orgSessionCount && endObjectCount == orgObjectCount) + break; + + test.Printf(_L("Warning: Session/object count leak\n")); + User::After(1000000); + } + + // some tests don't close their sessions, so this test won't work until + // all the tests are fixed : +// test(endSessionCount == orgSessionCount); +// test(endObjectCount == orgObjectCount); + + + // Test that the File cache hasn't leaked .... + r = controlIo(TheFs,theDrive, KControlIoFileCacheStats, endFileCacheStats); + test_Value(r, r == KErrNone || r == KErrNotSupported); + test.Printf(_L("File cache: Cachelines (free %d, used %d), Segments(allocated %d locked %d). Closed files(%d)\n"), + endFileCacheStats.iFreeCount, + endFileCacheStats.iUsedCount, + endFileCacheStats.iAllocatedSegmentCount, + endFileCacheStats.iLockedSegmentCount, + endFileCacheStats.iFilesOnClosedQueue); + if (r == KErrNone) + { + test(startFileCacheStats.iFreeCount == endFileCacheStats.iFreeCount); + test(startFileCacheStats.iUsedCount == endFileCacheStats.iUsedCount); + test(startFileCacheStats.iAllocatedSegmentCount == endFileCacheStats.iAllocatedSegmentCount); + test(startFileCacheStats.iLockedSegmentCount == endFileCacheStats.iLockedSegmentCount); + test(startFileCacheStats.iFileCount == endFileCacheStats.iFileCount); + } +#endif + + + +#if defined(_DEBUG) || defined(_DEBUG_RELEASE) + // Test that the request allocator hasn't leaked... TPckgBuf pkgValues; TIOCacheValues& values=pkgValues(); r = controlIo(TheFs,theDrive, KControlIoCacheCount, values); @@ -723,42 +809,6 @@ // + 1 (because we used one request to issue KControlIoCacheCount) // If this doesn't equate then this implies a request leak test(values.iTotalCount == values.iCloseCount + values.iFreeCount + 1); - - // File cache - TFileCacheStats endFileCacheStats; - r = controlIo(TheFs,theDrive, KControlIoFileCacheStats, endFileCacheStats); - test_Value(r, r == KErrNone || r == KErrNotSupported); - - test.Printf(_L("File cache: Cachelines (free %d, used %d), Segments(allocated %d locked %d). Closed files(%d)\n"), - endFileCacheStats.iFreeCount, - endFileCacheStats.iUsedCount, - endFileCacheStats.iAllocatedSegmentCount, - endFileCacheStats.iLockedSegmentCount, - endFileCacheStats.iFilesOnClosedQueue); - - // flush closed files queue - test.Printf(_L("Flushing close queue...")); - r = TheFs.ControlIo(theDrive, KControlIoFlushClosedFiles); - test_KErrNone(r); - - r = controlIo(TheFs,theDrive, KControlIoFileCacheStats, endFileCacheStats); - test_Value(r, r == KErrNone || r == KErrNotSupported); - test.Printf(_L("File cache: Cachelines (free %d, used %d), Segments(allocated %d locked %d). Closed files(%d)\n"), - endFileCacheStats.iFreeCount, - endFileCacheStats.iUsedCount, - endFileCacheStats.iAllocatedSegmentCount, - endFileCacheStats.iLockedSegmentCount, - endFileCacheStats.iFilesOnClosedQueue); - - - if (r == KErrNone) - { - test(startFileCacheStats.iFreeCount == endFileCacheStats.iFreeCount); - test(startFileCacheStats.iUsedCount == endFileCacheStats.iUsedCount); - test(startFileCacheStats.iAllocatedSegmentCount == endFileCacheStats.iAllocatedSegmentCount); - test(startFileCacheStats.iLockedSegmentCount == endFileCacheStats.iLockedSegmentCount); - test(startFileCacheStats.iFileCount == endFileCacheStats.iFileCount); - } #endif TheFs.Close(); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/server/t_rename.cpp --- a/kerneltest/f32test/server/t_rename.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/server/t_rename.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -15,6 +15,7 @@ // // +#define __E32TEST_EXTENSION__ #include #include #include "t_server.h" @@ -397,6 +398,83 @@ } +//------------------------------------------------------------------- +/** + Create a directory; create many files in it (the directory will become more that 1 cluster) + Then rename every file in this directory to a new name. +*/ +void TestRenameManyFilesInTheSameDir() +{ + test.Next(_L("TestRenameManyFilesInTheSameDir")); + + if(Is_Win32(TheFs, gDriveNum)) + { + test.Printf(_L("Skipping on WINS drive\n")); + return; + } + + _LIT(KDir, "\\dir1\\"); + _LIT(KFile, "filename_long-"); + + //-- the number of files is chosen the way to have the directory file at least 2 clusters long (on FAT) + //-- "filename_long-XXX" will correspond to 2 VFAT entries in the directory; max. cluster size of FAT is 32K + //-- 2*32*600 = 38400 > 32K + const TInt KNumFiles = 600; + + TName fName; + TInt i; + TInt nRes; + + //-- quick format the drive + nRes = FormatDrive(TheFs, gDriveNum, ETrue); + test_KErrNone(nRes); + + MakeDir(KDir); + + //-- create a number of files in a single directory, it shall be larger than 1 cluster. + for(i=0; iConstructL(); CleanupStack::Pop(r); @@ -89,13 +95,17 @@ void CScrollWindow::ConstructL() { - } +_LIT(KTxtPanic,"HUSBCONSAPP"); -CScrollWindow::CScrollWindow(CConsoleBase& aConsole) -: iConsole(aConsole) +CScrollWindow::CScrollWindow(CConsoleBase& aConsole, TInt aStartRow, TInt aEndRow) +: iConsole(aConsole), + iStartRow(aStartRow), + iEndRow(aEndRow), + iPageLength(iEndRow - iStartRow) { + __ASSERT_ALWAYS(iEndRow > iStartRow, User::Panic(KTxtPanic, -1)); } CScrollWindow::~CScrollWindow() @@ -130,12 +140,12 @@ void CScrollWindow::Update() { - TInt line = iPage * KPageLength; + TInt line = iPage * iPageLength; - TInt row = KStartRow_DriveInfo; + TInt row = iStartRow; do { - iConsole.SetPos(0, row + line%KPageLength); + iConsole.SetPos(0, row + line%iPageLength); if (line < iLineArray.Count()) { iConsole.Printf(iLineArray[line]); @@ -143,14 +153,15 @@ iConsole.ClearToEndOfLine(); line++; } - while (((line-1)%KPageLength) != (KPageLength - 1)); - iConsole.SetPos(0, KStartRow_DriveInfo + KPageLength); - iConsole.Printf(KScrollWindowStatus, iPage + 1, iLineArray.Count()/KPageLength + 1); + while (((line-1)%iPageLength) != (iPageLength - 1)); + + iConsole.SetPos(0, iStartRow + iPageLength); + iConsole.Printf(KScrollWindowStatus, iPage + 1, iLineArray.Count()/iPageLength + 1); } void CScrollWindow::PageInc() { - TInt lastPage = iLineArray.Count()/KPageLength; + TInt lastPage = iLineArray.Count()/iPageLength; if (iPage == lastPage) { iPage = 0; @@ -166,7 +177,7 @@ { if (iPage == 0) { - TInt lastPage = iLineArray.Count()/KPageLength; + TInt lastPage = iLineArray.Count()/iPageLength; iPage = lastPage; } else @@ -176,7 +187,6 @@ } - CDisplay* CDisplay::NewLC(RFs& aFs, CConsoleBase& aConsole) { CDisplay* r = new (ELeave) CDisplay(aFs, aConsole); @@ -187,8 +197,8 @@ void CDisplay::ConstructL() - { - iScrollWindow = CScrollWindow::NewL(iConsole); + { + iScrollWindow = CScrollWindow::NewL(iConsole, KRowScrollWindowStart, iScreenSize.iHeight - iFooterY - 4); } @@ -197,6 +207,9 @@ iConsole(aConsole) { iConsole.ClearScreen(); + iScreenSize = iConsole.ScreenSize(); + // Origin of footer + iPointFooter = TPoint(iFooterX, iScreenSize.iHeight - iFooterY - 2); } @@ -208,9 +221,9 @@ void CDisplay::Menu() { - iConsole.SetPos(0, KStartRow_UserKeys); + SetFooterPos(KPointUser1Keys); iConsole.Printf(KMsgUser1Keys); - iConsole.SetPos(0, KStartRow_UserKeys + 1); + SetFooterPos(KPointUser2Keys); iConsole.Printf(KMsgUser2Keys); iCursorPos = iConsole.CursorPos(); } @@ -592,7 +605,6 @@ line->Format(KFree, aVolumeInfo.iFree); line = iScrollWindow->NewLineL(); line->Format(KVolName, &aVolumeInfo.iName); - } @@ -600,14 +612,15 @@ { TUint totalMins = aUpTime/60; TUint totalHrs = totalMins/60; - iConsole.SetPos(0, KStartRow_UpTime); + + SetFooterPos(KPointSystemStatus); iConsole.Printf(KMsg_UpTime, totalHrs, totalMins%60, aUpTime%60); CursorHome(); } void CDisplay::MemoryFree(TInt aBytes) const { - iConsole.SetPos(0, KStartRow_MemoryFree); + SetFooterPos(KPointMemoryFree); iConsole.Printf(KMsg_MemoryFree, aBytes); CursorHome(); } @@ -684,6 +697,7 @@ TBool CMessageKeyProcessor::HandleKeyL(TKeyCode aKeyCode) { TBool done = EFalse; + if (TChar(aKeyCode).IsAlpha()) { iDisplay.GetDriveInfoL(aKeyCode); @@ -694,6 +708,7 @@ switch (aKeyCode) { case EKeyF5: + case EKeySpace: { // Update USB status iUsbOtgSession.DeviceInserted(); @@ -703,11 +718,13 @@ case EKeyUpArrow: case EKeyPageUp: + case '[': iDisplay.PageDec(); iDisplay.DriveInfo(); break; case EKeyDownArrow: case EKeyPageDown: + case ']': iDisplay.PageInc(); iDisplay.DriveInfo(); break; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/shostmassstorage/msman/app/cdisplay.h --- a/kerneltest/f32test/shostmassstorage/msman/app/cdisplay.h Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/shostmassstorage/msman/app/cdisplay.h Sat Feb 20 00:10:51 2010 +0200 @@ -33,11 +33,11 @@ class CScrollWindow: public CBase { public: - static CScrollWindow* NewL(CConsoleBase& aConsole); + static CScrollWindow* NewL(CConsoleBase& aConsole, TInt aStartRow, TInt aEndRow); ~CScrollWindow(); private: - CScrollWindow(CConsoleBase& aConsole); + CScrollWindow(CConsoleBase& aConsole, TInt aStartRow, TInt aEndRow); void ConstructL(); public: @@ -56,7 +56,9 @@ RArray iLineArray; TInt iPage; - static const TInt KPageLength = 8; + const TInt iStartRow; + const TInt iEndRow; + const TInt iPageLength; }; @@ -100,12 +102,20 @@ void CursorHome() const; -private: + void SetFooterPos(TPoint iPos) const; + +private: + static const TInt iFooterX = 0; + static const TInt iFooterY = 4; + RFs& iFs; CConsoleBase& iConsole; + TSize iScreenSize; TPoint iCursorPos; + TPoint iPointFooter; + CScrollWindow* iScrollWindow; }; @@ -115,7 +125,11 @@ iConsole.SetPos(iCursorPos.iX, iCursorPos.iY); } - +inline void CDisplay::SetFooterPos(TPoint iPos) const + { + TPoint pos = iPos + iPointFooter; + iConsole.SetPos(pos.iX, pos.iY); + } class CMessageKeyProcessor : public CActive { diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/transport/cbulkonlytransport.cpp --- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/transport/cbulkonlytransport.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/transport/cbulkonlytransport.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -928,7 +928,7 @@ DataOutReadRequest(deviceDataLength); } #else - DataOutRead(deviceDataLength); + DataOutReadRequest(deviceDataLength); #endif return; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 kerneltest/f32test/smassstorage/src/t_ms_mountstart.cpp --- a/kerneltest/f32test/smassstorage/src/t_ms_mountstart.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/f32test/smassstorage/src/t_ms_mountstart.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -701,6 +701,8 @@ fs.NotifyDismount(removalDrvNo, trsClientComplete, EFsDismountNotifyClients); test(trsClientComplete == KRequestPending); + fs.NotifyDismountCancel(trsClientComplete); + fs.Close(); dismountFs1.Close(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/etshell/ts_com.cpp --- a/userlibandfileserver/fileserver/etshell/ts_com.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/etshell/ts_com.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -43,7 +43,7 @@ TShellCommand(_L("CD"),_L("Change the current directory for a drive"),_L("[path] [/d]\n\n /d - Change drive"),TShellCommand::EDSwitch,ShellFunction::Cd), TShellCommand(_L("CHKDEPS"),_L("Check the dependencies of an executable or a Dll (ARM only)"),_L("[Filename.EXE] or [Filename.DLL]"),0,ShellFunction::ChkDeps), TShellCommand(_L("CHKDSK"),_L("Check disk for corruption"),_L("[drive:] [/s][/f|/u]\n\n/s - start ScanDrive instead of CheckDisk\n/f - finalise drive\n/u - unfinalise drive"),TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::EUSwitch,ShellFunction::ChkDsk), - TShellCommand(_L("COPY"),_L("Copy one (or more) file(s)"),_L("source [destination]"),TShellCommand::ESSwitch,ShellFunction::Copy), + TShellCommand(_L("COPY"),_L("Copy one (or more) file(s), overwriting existing one(s)"),_L("source [destination]"),TShellCommand::ESSwitch,ShellFunction::Copy), TShellCommand(_L("DEL"),_L("Delete one file"),_L("[drive:][path][filename]"),TShellCommand::ESSwitch,ShellFunction::Del), TShellCommand(_L("DIR"),_L("Show directory contents"),_L("[drive:][path][filename] [/p][/w]\n\n /p - Pause after each screen of information\n /w - Wide format"),TShellCommand::EPSwitch|TShellCommand::EWSwitch|TShellCommand::EASwitch,ShellFunction::Dir), // TShellCommand(_L("EDLIN"),_L("Edit a text file"),_L("[drive:][path][filename] [/p]\n\n /p - Pause after each screen of information"),TShellCommand::EPSwitch,ShellFunction::Edit), @@ -403,6 +403,8 @@ // To append files, specify a single file for destination, but multiple files // for source (using wildcards or file1+file2+file3 format). // +// Overwrites existing file(s). +// // My spec: // // COPY source [destination] @@ -461,6 +463,7 @@ } TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0); + // Automatically overwrites existing file(s) TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite; r=CShell::TheFileMan->Copy(dirPath.FullName(),destination,switches); if (r==KErrNone) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/group/release.txt --- a/userlibandfileserver/fileserver/group/release.txt Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/group/release.txt Sat Feb 20 00:10:51 2010 +0200 @@ -1,3 +1,57 @@ +Version 2.00.2031 +================= +(Made by vfebvre 26/01/2010) + +1. famustaf + 1. MINOR_CHANGE Add documentation to 'Copy' in Text Shell (TB9.2) + Added documentation to state that ShellFunction::Copy will overwrite existing file(s) + + +Version 2.00.2030 +================= +(Made by vfebvre 21/01/2010) + +1. dlyokhin + 1. PDEF143791 FAT: renaming many files in a directory corrupts short file names + + +Version 2.00.2029 +================= +(Made by vfebvre 19/01/2010) + +1. necliffo + 1. PDEF143913 WDP: T_locate fails on VASCO + + +Version 2.00.2028 +================= +(Made by vfebvre 15/01/2010) + +1. niccox + 1. PDEF143832 t_falsespace should not be run on drive if media type is EMediaRAM + + +Version 2.00.2027 +================= +(Made by vfebvre 15/01/2010) + +1. niccox + 1. PDEF143508 Host USB ModeSense10 command does not decode ModeDataLength + 2. MINOR_CHANGE usbtestclient corrections + 3. MINOR_CHANGE hostusbmsapp support for different screen sizes + 4. DEF143785 USB Host MS does not handle non-mass-storage drive correctly + +2. kaduan + 1. DEF143211 File system caching should be turned off on the S60 emulator + 2. DEF136627: T_HANDSHARE failed on NE1_TB_ARMV5.UDEB.SMPPAGE image + +3. migubarr + 1. DEF143592: t_ms_mountstart fails on H4 and VASCO + +4. dlyokhin + 1. PDEF143794 FAT: deleting VFAT entryset is not optimal + + Version 2.00.2026 ================= (Made by vfebvre 17/12/2009) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/inc/f32dbg.h --- a/userlibandfileserver/fileserver/inc/f32dbg.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/inc/f32dbg.h Sat Feb 20 00:10:51 2010 +0200 @@ -184,6 +184,9 @@ const TInt KControlIoFileCacheConfig=KMaxTInt-19; const TInt KControlIoSimulateFileCacheWriteFailure=KMaxTInt-20; +const TInt KControlIoSessionCount=KMaxTInt-21; +const TInt KControlIoObjectCount=KMaxTInt-22; + const TInt KNCDebugNotifierValue=-500000; // between 0 and 1 second GLREF_D TInt DebugNCNotifier; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/inc/f32file.h --- a/userlibandfileserver/fileserver/inc/f32file.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/inc/f32file.h Sat Feb 20 00:10:51 2010 +0200 @@ -1830,6 +1830,8 @@ #define EFSRV_IMPORT_C IMPORT_C #endif +// forward declarations from e32ldr_private.h +class RFileClamp; class RFs : public RSessionBase /** @@ -2167,7 +2169,6 @@ }; __ASSERT_COMPILE(_FOFF(TVolFormatParam, iUId) == 0); -__ASSERT_COMPILE(sizeof(TVolFormatParam) != sizeof(TLDFormatInfo)); /** package buffer for the objects of class TVolFormatParamBuf */ diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/inc/f32ver.h --- a/userlibandfileserver/fileserver/inc/f32ver.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/inc/f32ver.h Sat Feb 20 00:10:51 2010 +0200 @@ -58,6 +58,6 @@ @see TVersion */ -const TInt KF32BuildVersionNumber=2026; +const TInt KF32BuildVersionNumber=2031; // #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/fat_dir_entry.h --- a/userlibandfileserver/fileserver/sfat32/fat_dir_entry.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/fat_dir_entry.h Sat Feb 20 00:10:51 2010 +0200 @@ -97,8 +97,7 @@ inline void SetRuggedFatEntryId(TUint16 aId); public: - void InitializeAsVFat(TUint8 aCheckSum); - void SetVFatEntry(const TDesC& aName,TInt aRemainderLen); + void SetVFatEntry(const TDesC& aName, TUint aRemainderLen, TUint8 aCheckSum); void ReadVFatEntry(TDes16& aVBuf) const; inline TBool IsLongNameStart() const; inline TBool IsVFatEntry() const; @@ -110,6 +109,8 @@ TUint8 iData[KSizeOfFatDirEntry]; ///< The directory entry data }; +__ASSERT_COMPILE((sizeof(TFatDirEntry) == KSizeOfFatDirEntry)); +__ASSERT_COMPILE((sizeof(SFatDirEntry) == KSizeOfFatDirEntry)); #endif //FAT_DIR_ENTRY_H diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/fat_dir_entry.inl --- a/userlibandfileserver/fileserver/sfat32/fat_dir_entry.inl Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/fat_dir_entry.inl Sat Feb 20 00:10:51 2010 +0200 @@ -77,7 +77,10 @@ @return The size of file or directory for this entry */ inline TUint32 TFatDirEntry::Size() const - {return pDir->iSize;} + { + return pDir->iSize; + } + /** @return True if the entry is erased */ @@ -155,33 +158,35 @@ @param aFileSize Size of the file */ inline void TFatDirEntry::SetSize(TUint32 aFileSize) - {pDir->iSize=aFileSize;} -/** -Set the directory entry as erased -*/ + { + pDir->iSize=aFileSize; + } + +/** Set the directory entry as erased */ inline void TFatDirEntry::SetErased() - {iData[0]=KEntryErasedMarker;} -/** -Set the current entry to refer to the current directory -*/ + { + iData[0]=KEntryErasedMarker; + } + +/** Set the current entry to refer to the current directory */ inline void TFatDirEntry::SetCurrentDirectory() { iData[0]='.'; Mem::Fill(&iData[1],KFatDirNameSize-1,' '); } -/** -Set the current entry to refer to the parent directory -*/ + +/** Set the current entry to refer to the parent directory */ inline void TFatDirEntry::SetParentDirectory() { iData[0]='.';iData[1]='.'; Mem::Fill(&iData[2],KFatDirNameSize-2,' '); } -/** -Set the current entry to be the end of directory marker -*/ + +/** Set the current entry to be the end of directory marker */ inline void TFatDirEntry::SetEndOfDirectory() - {Mem::FillZ(&iData[0],KFatDirNameSize);} + { + Mem::FillZ(&iData[0],KFatDirNameSize); + } /** Get VFAT entry ID. Uset by Rugged FAT and Scan Drive to fix broken entries @@ -202,21 +207,23 @@ } -/** -@return True if the entry is the start of a long name set of entries -*/ +/** @return True if the entry is the start of a long name set of entries */ inline TBool TFatDirEntry::IsLongNameStart() const - {return (TBool)((iData[0]&0x40) != 0);} -/** -@return True is the Entry is a VFat entry -*/ + { + return (iData[0] & 0x40); + } + +/** @return True is the Entry is a VFat entry */ inline TBool TFatDirEntry::IsVFatEntry() const - {return (TBool)(Attributes()==KVFatEntryAttribute && IsEndOfDirectory()==EFalse);} -/** -@return The number of following VFat entries -*/ + { + return (Attributes()==KVFatEntryAttribute && IsEndOfDirectory() == EFalse); + } + +/** @return The number of following VFat entries */ inline TInt TFatDirEntry::NumFollowing() const - {return (iData[0]&0x3F);} + { + return (iData[0]&0x3F); + } inline TUint8 TFatDirEntry::CheckSum() const @@ -226,7 +233,6 @@ } - /** @return ETrue if the Directory entry contains garbage data */ diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/inc/sl_std.h --- a/userlibandfileserver/fileserver/sfat32/inc/sl_std.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/inc/sl_std.h Sat Feb 20 00:10:51 2010 +0200 @@ -63,12 +63,13 @@ class TEntryPos { public: - TEntryPos() {} + TEntryPos() : iCluster(EOF_32Bit), iPos(0) {} TEntryPos(TInt aCluster,TUint aPos) : iCluster(aCluster), iPos(aPos) {} inline TUint32 Cluster() const; inline TUint32 Pos() const; inline TBool operator==(const TEntryPos& aRhs) const; + inline void SetEndOfDir(); public: TInt iCluster; @@ -110,8 +111,13 @@ protected: TDriveInterface(); + ~TDriveInterface() {Close();} + + //-- outlawed TDriveInterface(const TDriveInterface&); TDriveInterface& operator=(const TDriveInterface&); + void* operator new(TUint); //-- disable creating objets of this class on the heap. + void* operator new(TUint, void*); TBool Init(CFatMountCB* aMount); void Close(); @@ -491,14 +497,12 @@ /** A wrapper around TDriveInterface providing its instantination and destruction. - You must not create objects of this class, use DriveInterface() instead. + You must not create objects of this class, use DriveInterface() method for obtaining the reference to the driver interface. */ class XDriveInterface: public TDriveInterface { public: - XDriveInterface() : TDriveInterface() {} - ~XDriveInterface() {Close();} - TBool Init(CFatMountCB* aMount) {return TDriveInterface::Init(aMount);} + using TDriveInterface::Init; }; @@ -538,9 +542,13 @@ inline TInt ClusterRelativePos(TInt aPos) const; inline TUint StartOfRootDirInBytes() const; inline TUint32 UsableClusters() const; + inline TBool ClusterNumberValid(TUint32 aClusterNo) const; inline TBool IsBadCluster(TInt aCluster) const; + inline TBool IsRuggedFSys() const; inline void SetRuggedFSys(TBool aVal); + inline TUint32 AtomicWriteGranularityLog2() const; + inline TInt RootIndicator() const; @@ -662,6 +670,24 @@ RArray iShortNameCandidates; }; + + /** a helper class that describes a continuous chunk of diectory entries*/ + class TEntrySetChunkInfo + { + public: + inline TEntrySetChunkInfo(); + inline TBool operator==(const TEntrySetChunkInfo& aRhs); + + //-- FAT entryset can't span more than 3 clusters/sectors + enum {KMaxChunks = 3}; + + public: + TEntryPos iEntryPos; ///< entryset chunk dir. starting position + TUint iNumEntries; ///< number of entries in the chunk + }; + + + void DoEraseEntrySetChunkL(const TEntrySetChunkInfo& aEntrySetChunk); TBool DoRummageDirCacheL(TUint anAtt,TEntryPos& aStartEntryPos,TFatDirEntry& aStartEntry,TEntryPos& aDosEntryPos,TFatDirEntry& aDosEntry,TDes& aFileName, const TFindHelper& aAuxParam, XFileCreationHelper* aFileCreationHelper, const TLeafDirData& aLeafDir) const; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/inc/sl_std.inl --- a/userlibandfileserver/fileserver/sfat32/inc/sl_std.inl Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/inc/sl_std.inl Sat Feb 20 00:10:51 2010 +0200 @@ -38,10 +38,29 @@ return (iCluster == aRhs.iCluster && iPos == aRhs.iPos); } +/** set "end of directory" indicator*/ +void TEntryPos::SetEndOfDir() + { + iCluster = EOF_32Bit; + } + //--------------------------------------------------------------------------------------------------------------------------------- // class CFatMountCB + +/** @return ETrue if the value of aClusterNo is valid*/ +inline TBool CFatMountCB::ClusterNumberValid(TUint32 aClusterNo) const + { + ASSERT(ConsistentState()); + + if(!aClusterNo && !Is32BitFat()) + return ETrue; //-- root dir. cluster for FAT12/16 + + return (aClusterNo >= KFatFirstSearchCluster) && (aClusterNo < UsableClusters()+KFatFirstSearchCluster); + } + + inline TInt CFatMountCB::RootDirectorySector() const {return iVolParam.RootDirectorySector();} @@ -159,17 +178,33 @@ /** Returns whether the current mount is running as rugged Fat or not, this is held in the file system object -@return Is rugged fat flag + @return ETrue if this is Rugged FAT */ TBool CFatMountCB::IsRuggedFSys() const - {return Drive().IsRugged();} + { + return Drive().IsRugged(); + } /** Sets the rugged flag in the file system object @param Flag to set or clear the rugged flag */ void CFatMountCB::SetRuggedFSys(TBool aVal) - {Drive().SetRugged(aVal);} + { + Drive().SetRugged(aVal); + } + +/** + @return Log2(Meida atomic write granularity). + This is mostly to be used in Rugged FAT mode, see IsRuggedFSys(). For Rugged FAT the media shall support atomic writes. + By default this is the sector (512 bytes) + +*/ +TUint32 CFatMountCB::AtomicWriteGranularityLog2() const + { + return KDefSectorSzLog2; + } + /** @return the usable clusters count for a volume */ TUint32 CFatMountCB::UsableClusters() const @@ -338,6 +373,21 @@ } +CFatMountCB::TEntrySetChunkInfo::TEntrySetChunkInfo() + :iNumEntries(KMaxTUint) + { + } + + +TBool CFatMountCB::TEntrySetChunkInfo::operator==(const TEntrySetChunkInfo& aRhs) + { + ASSERT(&aRhs != this); + return (iNumEntries == aRhs.iNumEntries) && (iEntryPos==aRhs.iEntryPos); + } + + + + //------- debug methods #ifdef _DEBUG /** diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_cache.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_cache.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_cache.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -28,19 +28,12 @@ CWTCachePage* CWTCachePage::NewL(TUint32 aPageSizeLog2) { CWTCachePage* pSelf = new (ELeave)CWTCachePage; - pSelf->ConstructL(aPageSizeLog2); + + pSelf->iData.CreateMaxL(1 << aPageSizeLog2); return pSelf; } -/** - 2nd stage constructor. - @param aPageSizeLog2 Log2(cache page size in bytes) -*/ -void CWTCachePage::ConstructL(TUint32 aPageSizeLog2) - { - iData.CreateMaxL(1 << aPageSizeLog2); - } CWTCachePage::CWTCachePage() { @@ -82,46 +75,45 @@ @param aDrive reference to the driver for media access. @param aNumPages number of cache pages to be created - @param aPageSizeLog2 Log2 of the page size in bytes + @param aPageSizeLog2 Log2 of the page size in bytes, this is the cache read granularity + @param aWrGranularityLog2 Log2(cache write granularity) @return a pointer to the created object. */ -CMediaWTCache* CMediaWTCache::NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2) +CMediaWTCache* CMediaWTCache::NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2) { -#ifndef ENABLE_DEDICATED_DIR_CACHE - //-- dedicated directory cache isn't enabled - (void)aDrive; //-- supress compiler's warning - (void)aClusterSizeLog2; - return NULL; -#else - - //-- dedicated directory cache is enabled, create it - ASSERT(aPageSizeLog2); - ASSERT(aNumPages); CMediaWTCache* pSelf = new (ELeave) CMediaWTCache(aDrive); CleanupStack::PushL(pSelf); - pSelf->ConstructL(aNumPages, aPageSizeLog2); + pSelf->InitialiseL(aNumPages, aPageSizeLog2, aWrGranularityLog2); CleanupStack::Pop(); return pSelf; - -#endif } /** 2nd stage constructor. @param aNumPages number of pages in the directory cache. - @param aPageSizeLog2 Log2(single cache page size in bytes) + @param aPageSizeLog2 Log2 of the page size in bytes, this is the cache read granularity + @param aWrGranularityLog2 Log2(cache write granularity) */ -void CMediaWTCache::ConstructL(TUint32 aNumPages, TUint32 aPageSizeLog2) +void CMediaWTCache::InitialiseL(TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2) { ASSERT(aNumPages && aPageSizeLog2); - __PRINT2(_L("#CMediaWTCache::CreateL() Pages=%d, PageSize=%d"), aNumPages, 1<= KDefSectorSzLog2 && aWrGranularityLog2 <= aPageSizeLog2); + } iPageSizeLog2 = aPageSizeLog2; + iWrGranularityLog2 = aWrGranularityLog2; //-- create cache pages for(TUint cnt=0; cntiStartPos; - return PageSize(); } @@ -483,9 +473,35 @@ if(dataLen <= bytesToPageEnd) {//-- data section completely fits to the cache page Mem::Copy(pPage->PtrInCachePage(aPos), pData, dataLen); //-- update cache + + //-- make small write a multiple of a write granularity size (if it is used at all) + //-- this is not the best way to use write granularity, but we would need to refactor cache pages code to make it normal + TPtrC8 desBlock(aDes); + + if(iWrGranularityLog2) + {//-- write granularity is used + const TInt64 newPos = (aPos >> iWrGranularityLog2) << iWrGranularityLog2; //-- round position down to the write granularity size + TUint32 newLen = (TUint32)(aPos - newPos)+dataLen; //-- round block size up to the write granularity size + newLen = RoundUp(newLen, iWrGranularityLog2); + + const TUint8* pd = pPage->PtrInCachePage(newPos); + desBlock.Set(pd, newLen); + aPos = newPos; + } + + + //-- write data to the media + const TInt nErr = iDrive.WriteCritical(aPos, desBlock); + if(nErr != KErrNone) + {//-- some serious problem occured during writing, invalidate cache. + InvalidateCache(); + User::Leave(nErr); + } + } else {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write + //-- this is a very rare case. TInt64 currMediaPos(aPos); //-- current media position @@ -523,9 +539,6 @@ Mem::Copy(pPage->PtrInCachePage(currMediaPos), pData, dataLen); } - }// else(dataLen <= bytesToPageEnd) - - //-- write data to the media const TInt nErr = iDrive.WriteCritical(aPos,aDes); if(nErr != KErrNone) @@ -534,6 +547,10 @@ User::Leave(nErr); } + }// else(dataLen <= bytesToPageEnd) + + + MakePageLRU(nPage); //-- push the page to the top of the priority list } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_cache.h --- a/userlibandfileserver/fileserver/sfat32/sl_cache.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_cache.h Sat Feb 20 00:10:51 2010 +0200 @@ -27,8 +27,6 @@ //--------------------------------------------------------------------------------------------------------------------------------- //-- dedicated FAT directory cache related stuff -//-- if defined, a dedicated cache will be used for FAT directories -#define ENABLE_DEDICATED_DIR_CACHE //--------------------------------------------------------------------------------------------------------------------------------- @@ -64,13 +62,10 @@ /** Finds out if the media position "aPosToSearch" is in the cache and returns cache page information in this case. - @param aPosToSearch linear media position to lookup in the cache - @param aCachedPosStart if "aPosToSearch" is cached, here will be media position of this page start - @return 0 if aPosToSearch isn't cached, otherwise cache page size in bytes (see also aCachedPosStart). */ - virtual TUint32 PosCached(const TInt64& aPosToSearch, TInt64& aCachedPosStart) = 0; + virtual TUint32 PosCached(TInt64 aPosToSearch) = 0; /** @return size of the cache in bytes. Can be 0. @@ -116,7 +111,6 @@ public: static CWTCachePage* NewL(TUint32 aPageSizeLog2); - void ConstructL(TUint32 aPageSizeLog2); ~CWTCachePage(); @@ -148,9 +142,7 @@ public: ~CMediaWTCache(); - static CMediaWTCache* NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2); - - void ConstructL(TUint32 aNumPages, TUint32 aPageSizeLog2); + static CMediaWTCache* NewL(TDriveInterface& aDrive, TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2); //-- overloads from the base class void ReadL (TInt64 aPos,TInt aLength,TDes8& aDes); @@ -159,7 +151,7 @@ void InvalidateCachePage(TUint64 aPos); - TUint32 PosCached(const TInt64& aPosToSearch, TInt64& aCachedPosStart); + TUint32 PosCached(TInt64 aPosToSearch); TUint32 CacheSizeInBytes() const; void MakePageMRU(TInt64 aPos); TUint32 PageSizeInBytesLog2() const; @@ -171,6 +163,8 @@ CMediaWTCache(); CMediaWTCache(TDriveInterface& aDrive); + void InitialiseL(TUint32 aNumPages, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2); + inline TInt64 CalcPageStartPos(TInt64 aPos) const; inline TUint32 PageSize() const; @@ -183,10 +177,14 @@ protected: TDriveInterface& iDrive; ///< reference to the driver for media access - TUint32 iPageSizeLog2; ///< Log2 (cache page size) + + TUint32 iPageSizeLog2; ///< Log2(cache page size or read granularity unit) + TUint32 iWrGranularityLog2; ///< Log2(cache write granularity unit). Can't be > iPageSizeLog2. '0' has a special meaning - "don't use write granularity" + mutable TBool iAllPagesValid;///< ETrue if all cache pages have valid data TInt64 iCacheBasePos; ///< Cache pages base position, used to align them at cluster size RPointerArray iPages; ///< array of pointers to the cache pages. Used for organising LRU list + TUint32 iCacheDisabled :1; ///< if not 0 the cache is disabled totally and all reads and writes go via TDriveInterface directly }; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_dir_cache.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -39,11 +39,11 @@ @param aStartRamAddr the start address in the ram that this page content lives */ TDynamicDirCachePage::TDynamicDirCachePage(CDynamicDirCache* aOwnerCache, TInt64 aStartMedPos, TUint8* aStartRamAddr) -:iStartMedPos(aStartMedPos), -iStartRamAddr(aStartRamAddr), -iOwnerCache(aOwnerCache), -iValid(EFalse), -iLocked(EFalse) + :iStartMedPos(aStartMedPos), + iStartRamAddr(aStartRamAddr), + iOwnerCache(aOwnerCache), + iValid(EFalse), + iLocked(EFalse) { //__PRINT3(_L("TDynamicDirCachePage::TDynamicDirCachePage(aStartMedPos=%lx, aStartRamAddr=0x%X, aPageSize=%u)"), aStartMedPos, aStartRamAddr, PageSizeInBytes()); iType = EUnknown; @@ -104,20 +104,22 @@ @param aDrive local drive interface to read/write media @param aMinPageNum the minimum page number for the cache, includes iActive page and locked pages. @param aMaxPageNum the maximum page number for the cache, includes iActive page, locked pages and unlocked pages. -@param aPageSizeInBytesLog2 the log2 value of page size in bytes, assumes page size is always a power of two + @param aPageSizeInBytesLog2 Log2 of the page size in bytes, this is the cache read granularity + @param aWrGranularityLog2 Log2(cache write granularity) */ -CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2) -:iPageSizeLog2(aPageSizeInBytesLog2), -iMinSizeInPages(aMinPageNum), -iMaxSizeInPages(aMaxPageNum), -iDrive(aDrive), -iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), -iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), -iLockedQCount(0), -iUnlockedQCount(0), -iHashFunction(HashFunction), -iIdentityFunction(IdentityFunction), -iLookupTable(iHashFunction, iIdentityFunction) +CDynamicDirCache::CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeInBytesLog2, TUint32 aWrGranularityLog2) + :iPageSizeLog2(aPageSizeInBytesLog2), + iWrGranularityLog2(aWrGranularityLog2), + iMinSizeInPages(aMinPageNum), + iMaxSizeInPages(aMaxPageNum), + iDrive(aDrive), + iLockedQ(_FOFF(TDynamicDirCachePage, iLink)), + iUnlockedQ(_FOFF(TDynamicDirCachePage, iLink)), + iLockedQCount(0), + iUnlockedQCount(0), + iHashFunction(HashFunction), + iIdentityFunction(IdentityFunction), + iLookupTable(iHashFunction, iIdentityFunction) { iPageSizeInBytes = 1 << aPageSizeInBytesLog2; iCacheDisabled = EFalse; @@ -174,10 +176,10 @@ /** Static factory function of CDynamicDirCache */ -CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName) +CDynamicDirCache* CDynamicDirCache::NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2, const TDesC& aClientName) { __PRINT3(_L("CDynamicDirCache::NewL(MinPageNum=%u, MaxPageNum=%u, page=%u)"), aMinPageNum, aMaxPageNum, 1<ConstructL(aClientName); CleanupStack::Pop(); @@ -338,7 +340,7 @@ @param aDataLen the length of the content to be written. @pre aDataLen should be no more than page size. */ -void CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) +TDynamicDirCachePage* CDynamicDirCache::WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen) { ASSERT(aDataLen <= iPageSizeInBytes); //-- the data section is in the cache page entirely, take data directly from the cache @@ -378,7 +380,8 @@ // always make writting events MRU DoMakePageMRU(aPos); - return; + + return pPage; } /** @@ -407,11 +410,37 @@ // __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd); if(dataLen <= bytesToPageEnd) - { - WriteDataOntoSinglePageL(aPos, pData, dataLen); + {//-- make small write a multiple of a write granularity size (if it is used at all) + //-- this is not the best way to use write granularity, but we would need to refactor cache pages code to make it normal + + TDynamicDirCachePage* pPage = WriteDataOntoSinglePageL(aPos, pData, dataLen); + TPtrC8 desBlock(aDes); + + if(iWrGranularityLog2) + {//-- write granularity is used + const TInt64 newPos = (aPos >> iWrGranularityLog2) << iWrGranularityLog2; //-- round position down to the granularity unit size + TUint32 newLen = (TUint32)(aPos - newPos)+dataLen; + newLen = RoundUp(newLen, iWrGranularityLog2); + + const TUint8* pd = pPage->PtrInPage(newPos); + desBlock.Set(pd, newLen); + aPos = newPos; + + } + + //-- write data to the media + const TInt nErr = iDrive.WriteCritical(aPos, desBlock); + if(nErr != KErrNone) + {//-- some serious problem occured during writing, invalidate cache. + InvalidateCache(); + User::Leave(nErr); + } + + } else - { + {//-- Data to be written cross cache page boundary or probably we have more than 1 page to write + //-- this is a very rare case. __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!")); //-- Data to be written cross cache page boundary or probably we have more than 1 page to write @@ -439,8 +468,6 @@ { WriteDataOntoSinglePageL(currMediaPos, pData, dataLen); } - }// else(dataLen <= bytesToPageEnd) - //-- write data to the media const TInt nErr = iDrive.WriteCritical(aPos,aDes); @@ -449,6 +476,11 @@ InvalidateCache(); User::Leave(nErr); } + + + }// else(dataLen <= bytesToPageEnd) + + } /** @@ -518,7 +550,7 @@ Implementation of pure virtual function. @see MWTCacheInterface::PosCached() */ -TUint32 CDynamicDirCache::PosCached(const TInt64& aPos, TInt64& aCachedPosStart) +TUint32 CDynamicDirCache::PosCached(TInt64 aPos) { const TInt64 pageStartMedPos = CalcPageStartPos(aPos); @@ -535,7 +567,6 @@ // __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) found on Unlocked Queue!"), aPos); // have to unlock it before returning, otherwise there will be memory leak UnlockPage(pPage); - aCachedPosStart = pPage->StartPos(); return pPage->PageSizeInBytes(); } else // if the unlocked page is not valid anymore, remove it @@ -551,7 +582,6 @@ else if (pPage) { __PRINT1(_L("CDynamicDirCache::PosCached: page(0x%lx) on Locked Queue!"), aPos); - aCachedPosStart = pPage->StartPos(); return pPage->PageSizeInBytes(); } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_dir_cache.h --- a/userlibandfileserver/fileserver/sfat32/sl_dir_cache.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_dir_cache.h Sat Feb 20 00:10:51 2010 +0200 @@ -105,6 +105,7 @@ //--------------------------------------------------------------------------------------------------------------------------------- typedef TDblQue TCachePageList; + /** Dynamic directory cache. For now it is directly derived from MWTCacheInterface. @@ -114,7 +115,7 @@ { public: ~CDynamicDirCache(); - static CDynamicDirCache* NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, const TDesC& aClientName); + static CDynamicDirCache* NewL(TDriveInterface& aDrive, TUint32 aMinPageNum, TUint32 aMaxPageNum, TUint32 aPageSizeLog2, TUint32 aWrGranularityLog2, const TDesC& aClientName); //-- overloads from the base class void ReadL (TInt64 aPos, TInt aLength, TDes8& aDes); @@ -122,7 +123,7 @@ void InvalidateCache(void); void InvalidateCachePage(TUint64 aPos); - TUint32 PosCached(const TInt64& aPosToSearch, TInt64& aCachedPosStart); + TUint32 PosCached(TInt64 aPosToSearch); TUint32 CacheSizeInBytes() const; TInt Control(TUint32 aFunction, TUint32 aParam1, TAny* aParam2); void SetCacheBasePos(TInt64 aBasePos); @@ -136,11 +137,12 @@ void Info() const; protected: - CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinSizeInBytes, TUint32 aMaxSizeInBytes, TUint32 aPageSizeInBytesLog2); + CDynamicDirCache(TDriveInterface& aDrive, TUint32 aMinSizeInBytes, TUint32 aMaxSizeInBytes, TUint32 aPageSizeInBytesLog2, TUint32 aWrGranularityLog2); void ConstructL(const TDesC& aClientName); void ReadDataFromSinglePageL(TInt64 aPos, TInt aLength, TDes8& aDes); - void WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen); + TDynamicDirCachePage* WriteDataOntoSinglePageL(TInt64 aPos, const TUint8* aData, TUint32 aDataLen); + TDynamicDirCachePage* FindPageByPos(TInt64 aPos); TDynamicDirCachePage* UpdateActivePageL(TInt64 aPos); TDynamicDirCachePage* AllocateAndLockNewPageL(TInt64 aStartMedPos); @@ -162,7 +164,9 @@ void DoInvalidateCache(void); private: - TUint32 iPageSizeLog2; ///< log2 value of cache pages size in bytes + TUint32 iPageSizeLog2; ///< Log2(cache page size or read granularity unit) + TUint32 iWrGranularityLog2; ///< Log2(cache write granularity unit). Can't be > iPageSizeLog2. '0' has a special meaning - "don't use write granularity" + TUint32 iMinCacheSizeInBytes; ///< minimum cache data size TUint32 iMaxCacheSizeInBytes; ///< maximum cache data size TUint32 iMinSizeInPages; ///< minimum cache page number diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_disk.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_disk.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_disk.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -126,7 +126,7 @@ const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page const TUint32 KUidCachePages = 64; //-- 64 pages; total cache size is 32K - iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2); + iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2, 0); //=========================== create directory cache @@ -185,7 +185,7 @@ TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:"); clientName.Append('A'+iFatMount->DriveNumber()); - TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName)); + TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, KDefSectorSzLog2, clientName)); if (err == KErrNone) return; @@ -197,7 +197,7 @@ //=========================== create legacy type of the directory cache ASSERT(!ipDirCache); - ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2); + ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2, KDefSectorSzLog2); __PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<LocalDrive()->SetMount(NULL); + } + iMount = NULL; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_mnt.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_mnt.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_mnt.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1064,6 +1064,13 @@ const TBool newFileExists = (nRes == KErrNone); //-- ETrue if 'aNewName' file exists. const TBool bNewNameIsVFAT = !IsLegalDosName(ptrNewName, EFalse, EFalse, EFalse, EFalse, ETrue); + if(!newFileExists) + {//-- invalidate directory iterators if aNewName doesn't exist + newName_VFatEntryPos.SetEndOfDir(); + aNewName_DosEntryPos.SetEndOfDir(); + } + + if(renameMode && newFileExists) { if(!namesAreIdentical) @@ -1143,7 +1150,7 @@ if (iFileCreationHelper.GetValidatedShortName(shortName) == KErrNotFound) { - GenerateShortNameL(aNewName_DosEntryPos.Cluster(), ptrNewName, shortName, ETrue); + GenerateShortNameL(aNewName_ParentDirPos.Cluster(), ptrNewName, shortName); } newDosEntry.SetName(shortName); @@ -1971,8 +1978,6 @@ TFatDirEntry StartEntry1(aStartEntry); TFatDirEntry DosEntry1(aDosEntry); - TInt64 nCachedLinPos; - const TUint32 clSize = 1 << ClusterSizeLog2(); //-- media cluster size const TUint32 cacheSz = pDirCache->CacheSizeInBytes(); //-- cache size in bytes const TUint32 maxDirEntries = cacheSz >> KSizeOfFatDirEntryLog2; //-- maximal number of dir entries that can be in the cache @@ -2021,7 +2026,7 @@ TBool PassedPageBoundary = EFalse; const TInt64 entryLinPos = MakeLinAddrL(DosEntryPos1); //-- linear media position of the cluster for this directory - const TUint32 cachePageSz = pDirCache->PosCached(entryLinPos, nCachedLinPos); //-- indicates if entryLinPos is cached + const TUint32 cachePageSz = pDirCache->PosCached(entryLinPos); //-- indicates if entryLinPos is cached if(cachePageSz) {//-- current page is in the directory cache //__PRINT2(_L("#-!! CFatMountCB::DoRummageDirCacheL() Searching cl:%d, lin Pos:%X"),DosEntryPos1.iCluster,(TUint32)entryLinPos); @@ -3961,18 +3966,14 @@ FOREVER { -#ifdef _DEBUG - const TInt e= GetDirEntry(aDosEntryPos, aDosEntry, startEntry, dummyLongName); - __PRINT1(_L("CFatMountCB::FindVolumeLabelFileL: GetDir %d"), e); - User::LeaveIfError(e); -#else User::LeaveIfError(GetDirEntry(aDosEntryPos, aDosEntry, startEntry, dummyLongName)); -#endif + if(aDosEntry.IsEndOfDirectory()) { __PRINT(_L("-CFatMountCB::FindVolumeLabelFileL: end of dir")); User::Leave(KErrNotFound); } + if(IsRootDir(aDosEntryPos) && (aDosEntryPos.iPos+StartOfRootDirInBytes()==(RootDirEnd()-KSizeOfFatDirEntry))) { if(aDosEntry.IsErased()) @@ -3981,28 +3982,31 @@ User::Leave(KErrNotFound); //Allows maximum number of entries in root directory } } + if(!aDosEntry.IsCurrentDirectory() && !aDosEntry.IsParentDirectory() && !aDosEntry.IsErased() && !aDosEntry.IsGarbage()) { if(aDosEntry.Attributes() & KEntryAttVolume) { aLabel = aDosEntry.Name(); -#ifdef _DEBUG dummyLongName.Copy(aLabel); __PRINT1(_L("-CFatMountCB::FindVolumeLabelFileL: found [%S]"), &dummyLongName); -#endif break; } } + MoveToNextEntryL(aDosEntryPos); + if(IsRootDir(aDosEntryPos) && (aDosEntryPos.iPos+StartOfRootDirInBytes()>=RootDirEnd())) { - __PRINT(_L("-CFatMountCB::FindVolumeLabelFileL: passed end of root")); + __PRINT(_L("-CFatMountCB::FindVolumeLabelFileL: Not found")); User::Leave(KErrNotFound); //Allows maximum number of entries in root directory } + if(aDosEntryPos.iCluster && (aDosEntryPos.iPos <= previousPosition)) { DoCheckFatForLoopsL(aDosEntryPos.iCluster, previousCluster, changePreviousCluster, count); } + previousPosition=aDosEntryPos.iPos; } } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfat32/sl_vfat.cpp --- a/userlibandfileserver/fileserver/sfat32/sl_vfat.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfat32/sl_vfat.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -29,11 +29,14 @@ // use second half of ISO Latin 1 character set for extended chars const TUint KExtendedCharStart=0x80; const TUint KExtendedCharEnd=0xff; +const TUint KMaxVFatEntries = 21; ///< Max possible number of entries in the VFAT entryset -LOCAL_C TBool IsLegalChar(TChar aCharacter,TBool aAllowWildChars,TBool aUseExtendedChars=EFalse,TBool aInScanDrive=EFalse) -// -// Returns ETrue if aCharacter is legal inside a dos filename -// + +//----------------------------------------------------------------------------- +/** + Returns ETrue if aCharacter is legal inside a dos filename +*/ +static TBool IsLegalChar(TChar aCharacter,TBool aAllowWildChars,TBool aUseExtendedChars=EFalse,TBool aInScanDrive=EFalse) { if ((aCharacter==KMatchOne) || (aCharacter==KMatchAny)) return(aAllowWildChars); @@ -46,7 +49,8 @@ return LocaleUtils::IsLegalShortNameCharacter(aCharacter,aUseExtendedChars); } -LOCAL_C void ReplaceFirstCharacterIfClashesWithE5L(TDes8& aShortName) +//----------------------------------------------------------------------------- +static void ReplaceFirstCharacterIfClashesWithE5L(TDes8& aShortName) { if (0 < aShortName.Length() && aShortName[0] == KEntryErasedMarker) { @@ -54,7 +58,8 @@ } } -LOCAL_C void ReplaceIllegalCharactersL(TDes& aLongName, TUint aCharacterToReplaceWith) +//----------------------------------------------------------------------------- +static void ReplaceIllegalCharactersL(TDes& aLongName, TUint aCharacterToReplaceWith) { TBool alreadyFoundExtensionDelimiter=EFalse; @@ -130,10 +135,11 @@ } } +//----------------------------------------------------------------------------- +/** + Create a legal shortname from aLongName +*/ TShortName DoGenerateShortNameL(const TDesC& aLongName,TInt& aNum,TBool aUseTildeSelectively) -// -// Create a legal shortname from aLongName -// { TFileName longName(aLongName); @@ -259,7 +265,7 @@ return shortName; } - +//----------------------------------------------------------------------------- /** Check whether a Dos name is legal or not. @@ -271,7 +277,6 @@ @return ETrue if the name is a legal DOS one. */ - static TBool DoCheckLegalDosName(const TDesC& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) { const TInt count=aName.Length(); @@ -388,6 +393,7 @@ return ETrue; } +//----------------------------------------------------------------------------- /** Check whether a Dos name is legal or not. Unicode version parameters and return value absolutely the same as in DoCheckLegalDosName() @@ -395,18 +401,19 @@ TBool IsLegalDosName(const TDesC16& aName, TBool anAllowWildCards, TBool aUseExtendedChars, TBool aInScanDrive, TBool aAllowLowerCase, TBool aIsForFileCreation) { - __PRINT(_L("IsLegalDosName 16")); + //__PRINT(_L("IsLegalDosName 16")); return DoCheckLegalDosName(aName, anAllowWildCards, aUseExtendedChars, aInScanDrive, aAllowLowerCase, aIsForFileCreation); } +//----------------------------------------------------------------------------- +/** + Returns ETrue and the entryPos of aName if found or EFalse +*/ TBool CFatMountCB::FindShortNameL(const TShortName& aName,TEntryPos& anEntryPos) -// -// Returns ETrue and the entryPos of aName if found or EFalse -// { - __PRINT(_L("VFAT::CFatMountCB::FindShortNameL")); + __PRINT(_L("CFatMountCB::FindShortNameL")); TFatDirEntry fatEntry; TInt count=0; FOREVER @@ -428,27 +435,29 @@ return EFalse; } +//----------------------------------------------------------------------------- +/** + Returns ETrue if aName is unique, EFalse if a matching name is found. +*/ TBool CFatMountCB::IsUniqueNameL(const TShortName& aName,TInt aDirCluster) -// -// Returns ETrue if aName is unique, EFalse if a matching name is found. -// { - __PRINT(_L("VFAT::CFatMountCB::IsUniqueNameL")); + __PRINT(_L("CFatMountCB::IsUniqueNameL")); TEntryPos entryPos(aDirCluster,0); if (FindShortNameL(aName,entryPos)) return(EFalse); return(ETrue); } +//----------------------------------------------------------------------------- +/** + A legal dos name has been typed that clashes with a computer generated shortname + Change the shortname to something else. +*/ void CFatMountCB::ReplaceClashingNameL(const TShortName& aNewName,const TEntryPos& anEntryPos) -// -// A legal dos name has been typed that clashes with a computer generated shortname -// Change the shortname to something else. -// { - __PRINT(_L("VFAT::CFatMountCB::ReplaceClashingNameL")); + __PRINT(_L("CFatMountCB::ReplaceClashingNameL")); TFatDirEntry entry; ReadDirEntryL(anEntryPos,entry); __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); @@ -469,14 +478,22 @@ } } +//----------------------------------------------------------------------------- +/** + Generate a legal dos filename as an alias for aName. + @return ETrue if aName is a legal dos name. +*/ TBool CFatMountCB::GenerateShortNameL(TInt aDirCluster,const TDesC& aName,TShortName& aGeneratedName, TBool aForceRandomize) -// -// Generate a legal dos filename as an alias for aName. -// Returns ETrue if aName is a legal dos name. -// { - __PRINT(_L("VFAT::CFatMountCB::GenerateShortNameL")); + __PRINT1(_L("CFatMountCB::GenerateShortNameL() cl:%d"), aDirCluster); + + if(!ClusterNumberValid(aDirCluster)) + { + ASSERT(0); + User::Leave(KErrCorrupt); + } + // Given the long file-name "ABCDEFGHI.TXT", EPOC used to generate short // file-names in the following pecking order: // "ABCDEFGH.TXT", @@ -546,142 +563,307 @@ } -void TFatDirEntry::InitializeAsVFat(TUint8 aCheckSum) -// -// Initialize a FAT entry as a VFAT filename -// + +//----------------------------------------------------------------------------- +/** + Write up to KMaxVFatEntryName unicode chars from aName to the entry + @param aName long file name part that will be converted into the VFAT entryset + @param aLen length of the remaining name + @param aCheckSum DOS entry name checksum. +*/ +void TFatDirEntry::SetVFatEntry(const TDesC& aName, TUint aLen, TUint8 aCheckSum) { - - Mem::Fill(this,sizeof(SFatDirEntry),0xFF); + //-- initialise some VFAT entry specific fields iData[0x0B]=0x0F; iData[0x0C]=0x00; iData[0x0D]=aCheckSum; iData[0x1A]=0x00; iData[0x1B]=0x00; - } - -void TFatDirEntry::SetVFatEntry(const TDesC& aName,TInt aLen) -// -// Write up to KMaxVFatEntryName unicode chars from aName to the entry -// - { TInt rem=aName.Length()-aLen; TPtrC section(aName.Ptr()+aLen,Min(rem,KMaxVFatEntryName)); TBuf16 buf16; buf16.Copy(section); + if (remdefault size - TInt dosOffset=numEntries<>SectorSizeLog2())==0 && ((TUint)(1<= ((numEntries+1)<SetVFatEntry(aLongName, KMaxVFatEntryName*(numEntries-1), cksum); //KMaxVFatEntryName=13 + + posInBuf += KSizeOfFatDirEntry; + MoveToNextEntryL(aPos); + + numEntries--; + movedCluster = (startPos.Cluster() != aPos.Cluster()); //-- if moved to another cluser, need to flush buffer + + if(!numEntries || movedCluster) + break; //-- VFAT entryset is completed + } + + if(movedCluster) + { + DirWriteL(startPos, TPtrC8(&scratchBuf[0], posInBuf)); + continue; + } + + if(!numEntries) + {//-- need to append DOS entry + Mem::Copy(&scratchBuf[posInBuf], &aDosEntry, KSizeOfFatDirEntry); + posInBuf+= KSizeOfFatDirEntry; + DirWriteL(startPos, TPtrC8(&scratchBuf[0], posInBuf)); + break; + } + + }//for(;;) + } + + + +//--------------------------------------------------------------------------------- + +void CFatMountCB::DoEraseEntrySetChunkL(const TEntrySetChunkInfo& aEntrySetChunk) + { + + //-- scratch buffer for whole VFAT entryset. Max number of entries in it is 21 entry or 672 bytes. + //-- in the worst case the entryset can span across 3 clusters (512 bytes per cluster) + //-- Using the scratch buffer is not ideal, but write-back directory cache isn't in place yet + + const TUint KBufSize = 680; + TBuf8 scratchBuf; + + TUint numEntries = aEntrySetChunk.iNumEntries; + + ASSERT(numEntries >0 && numEntries <= KMaxVFatEntries); + const TUint32 KChunkLen = numEntries << KSizeOfFatDirEntryLog2; + + DirReadL(aEntrySetChunk.iEntryPos, KChunkLen, scratchBuf); + + TInt posInBuf = 0; while (numEntries--) { - vFatEntry.SetVFatEntry(aLongName,KMaxVFatEntryName*numEntries);// KMaxVFatEntryName=13 - if(isSameSector) - { - Mem::Copy(&localBuf[offset],&vFatEntry,KSizeOfFatDirEntry); - offset+=KSizeOfFatDirEntry; - MoveToNextEntryL(aPos); - } - else - { - WriteDirEntryL(aPos,vFatEntry); - MoveToNextEntryL(aPos); - } - } - if(isSameSector) - { - Mem::Copy(&localBuf[offset],&aFatDirEntry,KSizeOfFatDirEntry); - - //-- use special interface to access FAT directory file - DirWriteL(startPos,TPtrC8(&localBuf[0],dosOffset+KSizeOfFatDirEntry)); + TFatDirEntry* pEntry = (TFatDirEntry*)(scratchBuf.Ptr()+posInBuf); + pEntry->SetErased(); + posInBuf += KSizeOfFatDirEntry; } - else - WriteDirEntryL(aPos,aFatDirEntry); - } + + DirWriteL(aEntrySetChunk.iEntryPos, scratchBuf); + } +//--------------------------------------------------------------------------------- +/** + Erase whole VFAT entryset. + For Rugged FAT the situation is more complicated: we need firstly delete the DOS entry _atomically_ i.e. if this operation fails, + the whole VFAT entryset won't be broken. Deleting VFAT entries doesn't require the atomic media writes; DOS entry contains necessary + information about data stream. + + @param aPos position of the entryset start in the directory. + @param aFirstEntry first entry in the entryset, it can be DOS entry + +*/ void CFatMountCB::EraseDirEntryL(TEntryPos aPos,const TFatDirEntry& aFirstEntry) -// -// Mark all entries in a VFat directory entry as erased -// { - __PRINT(_L("VFAT::CFatMountCB::EraseDirEntryL")); - TInt numEntries=0; + __PRINT2(_L("CFatMountCB::EraseDirEntryL() cl:%d, offset:%d"), aPos.Cluster(), aPos.Pos()); + + TUint numEntries=0; if (aFirstEntry.IsVFatEntry()) + { numEntries=aFirstEntry.NumFollowing(); - if(IsRuggedFSys()&&numEntries) - { - TInt count=numEntries; - TEntryPos pos=aPos; - while(count--) - MoveToNextEntryL(pos); - EraseDirEntryL(pos); - numEntries--; + numEntries++; //-- take into account the last DOS entry } - FOREVER - { + else + {//-- we are deleting a single DOS entry. This is an atomic operation. EraseDirEntryL(aPos); - if (!numEntries--) - break; - MoveToNextEntryL(aPos); - } - } + return; + } + + ASSERT(numEntries > 1 && numEntries <= KMaxVFatEntries); + + TEntrySetChunkInfo chunksInfo[TEntrySetChunkInfo::KMaxChunks]; + + //-- 1. check if the entryset fits into a unit of write ganularity. This will be 1 sector for rugged FAT or 1 cluster otherwise + + TUint32 MaxWriteGranularityLog2; + + if(IsRuggedFSys()) + { + MaxWriteGranularityLog2 = AtomicWriteGranularityLog2(); + } + else if(IsRootDir(aPos)) + {//-- root dir. for FAT12/16 is a special case, it is not made of clusters. it's unit is 1 sector. + MaxWriteGranularityLog2 = KDefSectorSzLog2; + } + else + {//-- minimal unit size will be a cluster + MaxWriteGranularityLog2 = ClusterSizeLog2(); + } + + + { + const TUint64 KEntrySetStartPos = MakeLinAddrL(aPos); + const TUint64 KEntrySetLogicalEndPos = KEntrySetStartPos + (numEntries << KSizeOfFatDirEntryLog2); + + const TUint64 KBlockEndPos = ((KEntrySetLogicalEndPos-1) >> MaxWriteGranularityLog2) << MaxWriteGranularityLog2; + const TUint64 KBlockStartPos = (KEntrySetStartPos >> MaxWriteGranularityLog2) << MaxWriteGranularityLog2; + + if(KBlockEndPos == KBlockStartPos) + {//-- whole entryet is in the same block; the whole entryset erase operation will be atomic for Rugged/non-rugged FAT + chunksInfo[0].iEntryPos = aPos; + chunksInfo[0].iNumEntries = numEntries; + DoEraseEntrySetChunkL(chunksInfo[0]); + return; + } + + } + + //-- the entryset is split on max. 3 parts between units of write granularity (see MaxWriteGranularityLog2). + ASSERT(numEntries > 1 && numEntries <= KMaxVFatEntries); + + TInt cntChunk = 1; //-- there is at least 1 entries chunk + TEntrySetChunkInfo* pChunkInfo = chunksInfo; + + //-- collect information about dir. entry chunks that reside in different units of write granularity + for(;;) + { + TBool movedUnit = EFalse; + pChunkInfo->iEntryPos = aPos; + pChunkInfo->iNumEntries = 0; + + const TUint64 KChunkStartPos = MakeLinAddrL(aPos); + const TUint64 KChunkBlockStartPos = (KChunkStartPos >> MaxWriteGranularityLog2) << MaxWriteGranularityLog2; + const TUint64 KChunkBlockEndPos = (KChunkBlockStartPos-1) + (1<iNumEntries++; + MoveToNextEntryL(aPos); + + numEntries--; + const TUint64 currPos = MakeLinAddrL(aPos); + movedUnit = !(currPos >= KChunkBlockStartPos && currPos <= KChunkBlockEndPos); + + if(!numEntries || movedUnit) + { + break; + } + + } + + if(movedUnit && numEntries) + {//-- move to the next unit of write granularity + ++pChunkInfo; + ++cntChunk; + ASSERT(cntChunk <= TEntrySetChunkInfo::KMaxChunks); + continue; + } + + + ASSERT(!numEntries); + break; + } + + //-- now do bulk deletion, write data based on collected entries chunks. + ASSERT(cntChunk > 0); + + //-- if it is a rugged FAT, we need to delete DOS entry first; it will be in the last chunk. + if(IsRuggedFSys()) + { + const TInt dosEntryChunk = cntChunk-1; + DoEraseEntrySetChunkL(chunksInfo[dosEntryChunk]); + cntChunk--; + } + + //-- it is also possible to joint entryset chunks together here if they belong to the same cluster. + //-- the atomic write here is not required. + + //-- erase the rest of entries in reamining chunks. + for(TInt i=0; i pkgBuf(SessionCount); + TInt r=aRequest->Write(2,pkgBuf); + return r; + } + case KControlIoObjectCount: + { + TPckgBuf pkgBuf(ObjectCount); + TInt r=aRequest->Write(2,pkgBuf); + return r; + } + } #endif diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_memory_client.cpp --- a/userlibandfileserver/fileserver/sfile/sf_memory_client.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_memory_client.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -34,11 +34,7 @@ { const TUint32 segCnt = iTouchedRegionFlag <= iReservedRegionMarkInSegs ? iReservedRegionMarkInSegs : iTouchedRegionFlag; - TInt r = DecommitSegments(iBase, segCnt); - if (r != KErrNone) // this 'if() {}' is to remove build warnings - { - ASSERT(0); - } + DecommitSegments(iBase, segCnt); iReusablePagePool.Close(); delete iName; } @@ -95,7 +91,6 @@ iBase = iManager.Base() + aOffsetInBytes; iReservedRegionMarkInSegs = iMinSizeInSegs; TInt r = iManager.AllocateAndLockSegments(iBase, iReservedRegionMarkInSegs); - ASSERT(r==KErrNone); User::LeaveIfError(r); iTouchedRegionFlag = 0; __PRINT(_L("CCacheMemoryClient::ConstructL() return 0")); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_memory_man.cpp --- a/userlibandfileserver/fileserver/sfile/sf_memory_man.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_memory_man.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -125,10 +125,9 @@ // if it is a new drive/file system who wants to connect, create a new client for it // parameter validation - ASSERT(iSizeInBytes > iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())); if (iSizeInBytes < iCurrentOffsetMark + (aMaxSizeInSegs << SegmentSizeInBytesLog2())) { - ASSERT(0); + __PRINT1(_L("CCacheMemoryManager::ConnectClientL([%S]) failed, please check \"GlobalCacheMemorySize\" setting!!!"), &aClientName); User::Leave(KErrArgument); } @@ -140,7 +139,6 @@ TInt err = iRegisteredClients.Append(client); if (err != KErrNone) { - ASSERT(0); delete client; client = NULL; User::Leave(err); @@ -289,7 +287,10 @@ */ void CCacheMemoryManagerFactory::CreateL() { - iCacheMemoryManager = CCacheMemoryManager::NewL(TGlobalCacheMemorySettings::CacheSize()); + if (TGlobalCacheMemorySettings::CacheSize() > 0) + iCacheMemoryManager = CCacheMemoryManager::NewL(TGlobalCacheMemorySettings::CacheSize()); + else + __PRINT(_L("\"GlobalCacheMemorySize\" set <= 0, CCacheMemoryManager is not created!!!")); } /** diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_notify.cpp --- a/userlibandfileserver/fileserver/sfile/sf_notify.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_notify.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -333,6 +333,18 @@ return(isFound); } +CNotifyInfo* TBaseQue::DoFindEntry(CSessionFs* aSession, TRequestStatus* aStatus) + { + TDblQueIter q(iHeader); + CNotifyInfo* info; + while((info=q++)!=NULL) + { + if(info->Session()==aSession && (!aStatus || aStatus==info->Status())) + return info; + } + return NULL; + } + void TBaseQue::DoCancelAll(TInt aCompletionCode) // // Cancel all notifications @@ -654,13 +666,20 @@ TInt TDismountNotifyQue::CancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus) // -// +// Returns the drive number or KErrNotFound // { iQLock.Wait(); - TBool isFound=TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + + // return the drive number + CDismountNotifyInfo* info = (CDismountNotifyInfo*) DoFindEntry(aSession, aStatus); + TInt driveNumber = info ? info->DriveNumber() : KErrNotFound; + + TBaseQue::DoCancelSession(aSession,aCompletionCode,aStatus); + iQLock.Signal(); - return(isFound); + + return(driveNumber); } void TDismountNotifyQue::CancelAll(TInt aCompletionCode) @@ -929,14 +948,15 @@ iDebugQue.CancelSession(aSession,KErrCancel,aStatus); } -void FsNotify::CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus) +TInt FsNotify::CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus) // // Cancel all media removal notification(s) setup by aSession (if aStatus == NULL) -// else cancels all oustanding notifications(s) for the session +// else cancels all outstanding notifications(s) for the session // { __PRINT2(_L("FsNotify::CancelDismountNotifySession() aSession=0x%x aStatus=0x%x"),aSession,aStatus); - iDismountNotifyQue.CancelSession(aSession,KErrCancel,aStatus); + TInt drive = iDismountNotifyQue.CancelSession(aSession,KErrCancel,aStatus); + return drive; } void FsNotify::CancelSession(CSessionFs* aSession) diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_obj.cpp --- a/userlibandfileserver/fileserver/sfile/sf_obj.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_obj.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -156,7 +156,9 @@ */ EXPORT_C CFsObject::CFsObject() { - +#if defined(_DEBUG) || defined(_DEBUG_RELEASE) + __e32_atomic_add_ord32(&ObjectCount, 1); +#endif // iContainer=NULL; // iName=NULL; iAccessCount=1; @@ -179,6 +181,9 @@ __ASSERT_ALWAYS(!iContainer,Fault(EObjDestructorContainer)); if(iName) User::Free(iName); +#if defined(_DEBUG) || defined(_DEBUG_RELEASE) + __e32_atomic_add_ord32(&ObjectCount, (TUint32) -1); +#endif } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_ses.cpp --- a/userlibandfileserver/fileserver/sfile/sf_ses.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_ses.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -27,6 +27,9 @@ iReservedDriveAccess(KReservedDriveAccessArrayGranularity, _FOFF(TReservedDriveAccess, iDriveNumber)), iId(0) { +#if defined(_DEBUG) || defined(_DEBUG_RELEASE) + __e32_atomic_add_ord32(&SessionCount, 1); +#endif } CSessionFs *CSessionFs::NewL() @@ -64,6 +67,10 @@ iSessionFlagsLock.Close(); if(iDisconnectRequest) delete(iDisconnectRequest); + +#if defined(_DEBUG) || defined(_DEBUG_RELEASE) + __e32_atomic_add_ord32(&SessionCount, (TUint32) -1); +#endif } void CSessionFs::CreateL() diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_std.h --- a/userlibandfileserver/fileserver/sfile/sf_std.h Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_std.h Sat Feb 20 00:10:51 2010 +0200 @@ -1511,6 +1511,7 @@ ~CDismountNotifyInfo(); void Initialise(TNotifyDismountMode aMode, TInt aDriveNumber,TRequestStatus* iStatus,const RMessagePtr2& aMessage,CSessionFs* aSession); TBool IsMatching(TNotifyDismountMode aMode, TInt aDriveNumber, CSessionFs* aSession); + inline TInt DriveNumber() {return iDriveNumber;} private: TNotifyDismountMode iMode; TInt iDriveNumber; @@ -1527,6 +1528,7 @@ void DoAddNotify(CNotifyInfo* aInfo); TBool DoCancelSession(CSessionFs* aSession,TInt aCompletionCode,TRequestStatus* aStatus=NULL); void DoCancelAll(TInt aCompletionCode); + CNotifyInfo* DoFindEntry(CSessionFs* aSession, TRequestStatus* aStatus=NULL); TBool IsEmpty(); protected: TDblQue iHeader; @@ -1597,7 +1599,7 @@ static void CancelChangeSession(CSessionFs* aSession,TRequestStatus* aStatus=NULL); static void CancelDiskSpaceSession(CSessionFs* aSession,TRequestStatus* aStatus=NULL); static void CancelDebugSession(CSessionFs* aSession, TRequestStatus* aStatus=NULL); - static void CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus=NULL); + static TInt CancelDismountNotifySession(CSessionFs* aSession, TRequestStatus* aStatus=NULL); static void CancelSession(CSessionFs* aSession); static TBool HandlePendingDismount(CSessionFs* aSession, TInt aDriveNumber); static TBool IsChangeQueEmpty(TInt aDrive); @@ -1803,6 +1805,8 @@ extern TInt UserHeapAllocFailCount; extern TInt KernHeapAllocFailCount; extern TInt MessageCount; +extern TInt SessionCount; +extern TInt ObjectCount; void PrintHeapSize(const TDesC& aMessage); diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/sfile/sf_sys.cpp --- a/userlibandfileserver/fileserver/sfile/sf_sys.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/sfile/sf_sys.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -1223,7 +1223,9 @@ // { CSessionFs* session = aRequest->Session(); - FsNotify::CancelDismountNotifySession(session, (TRequestStatus*)aRequest->Message().Ptr0()); + TInt drive = FsNotify::CancelDismountNotifySession(session, (TRequestStatus*)aRequest->Message().Ptr0()); + if (drive >= 0) + TheDrives[drive].SetDismountDeferred(EFalse); return KErrNone; } diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/shostmassstorage/server/protocol/cscsiprotocol.cpp --- a/userlibandfileserver/fileserver/shostmassstorage/server/protocol/cscsiprotocol.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/shostmassstorage/server/protocol/cscsiprotocol.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -353,13 +353,13 @@ if (info.iPeripheralQualifier != 0 && info.iPeripheralQualifier != 1) { __HOSTPRINT(_L("Peripheral Qualifier[Unknown device type]\n")) - return KErrNotSupported; + return KErrUnknown; } if (info.iPeripheralDeviceType != 0) { __HOSTPRINT(_L("Peripheral Device Type[Unsupported device type]\n")) - return KErrNotSupported; + return KErrUnknown; } iRemovableMedia = info.iRemovable; diff -r 2d65c2f76d7b -r 4a8fed1c0ef6 userlibandfileserver/fileserver/shostmassstorage/server/protocol/tscsiblockcmds.cpp --- a/userlibandfileserver/fileserver/shostmassstorage/server/protocol/tscsiblockcmds.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/userlibandfileserver/fileserver/shostmassstorage/server/protocol/tscsiblockcmds.cpp Sat Feb 20 00:10:51 2010 +0200 @@ -57,7 +57,7 @@ } TInt modeDataLength = aPtr[0]; - if (aPtr.Length() - 1 < modeDataLength) + if (aPtr.Length() - 1 > modeDataLength) { User::Leave(KErrGeneral); } @@ -121,8 +121,8 @@ User::Leave(KErrGeneral); } - TInt modeDataLength = BigEndian::Get32(&aPtr[0]); - if (aPtr.Length() - 2 < modeDataLength) + TInt modeDataLength = BigEndian::Get16(&aPtr[0]); + if (aPtr.Length() - 2 > modeDataLength) { User::Leave(KErrGeneral); }