diff -r 000000000000 -r 96e5fb8b040d userlibandfileserver/fileserver/estart/estart.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/estart/estart.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,2478 @@ +// Copyright (c) 1998-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: +// f32\estart\estart.cpp +// Generic startup code run by the fileserver on boot +// +// + +#include +#include +#include +#include +#include +#include +#include +#ifndef SYMBIAN_EXCLUDE_ESTART_DOMAIN_MANAGER +#include +#endif +#include +#include + +//#ifndef _DEBUG +// #define _DEBUG +//#endif +//#define TRACING_ON + +#include "estart.h" +#include + +//-- define this macro in order to have system start time measurement (SYSSTATEMGR.EXE process life time) +//#define SYMBIAN_ESTART_OUTPUT_BOOT_TIME + + +TInt LoadCodePageDll(); +/** Maximum Codepage Dll name length. */ +const TInt KMaxCodepageDllName=16; + + +#ifdef _DEBUG +TBool DebugTraceEnabled() + { +#ifdef TRACING_ON + return ETrue; +#else + return UserSvr::DebugMask() & 2; +#endif + } +#endif + +_LIT(KEStartPanicCatagory, "ESTART"); + +enum TEStartPanic + { + ELitNoDM = 1, // No Domain Manager + ELitDMInitFail, // Domain Manager init fail + ELitHALFail, // HAL init fail + ELitConnectFsFail1, // Connect fs 1 fail + ELitInitLocalPwStoreFail, // Init PwStore fail + ELitLocaleInitialisationFail, // Initialisation of locale properties failed + ELitFSInitDriveInfoFail, // FS Init DriveInfo fail + ELitCreateTrapHandlerFail, // Create trap handler fail + ELitLoadSysLddsFail, // Load sys ldds fail + ELitLocalDriveMappingFail, // Local drive mapping fail + ELitDriveMappingFileFail, // Drive mapping file not found + ELitSwapMappingFailArrayInconsistent, // Swap mappings fail - array inconsistent + ELitFsSwapMappingFail, // Swap mappings fail - Fs request failed + EPropertyError, // RProperty return error + ECompMountFsFail, // Failed comp fs mount + EFsNameFail, // File system name on Z: failed + ELitNoWS, // No WSERV + EStartupModeFail, // Get startup mode failed + ESysAgentFail, // Fail to launch system agent + ESetSystemDriveFail // Fail to set System Drive + }; + +inline void Panic(TEStartPanic aPanic, TInt aReason) + { + TBuf<10> panic(KEStartPanicCatagory); + panic.AppendFormat(_L("_%d"), aPanic); + User::Panic(panic, aReason); + } + +_LIT(KRofs,"erofs.fsy"); +_LIT(KCompfs,"ecomp.fsy"); +_LIT(KEcomp,"ECOMP"); +_LIT(KServerPathSysBin, "0:\\Sys\\Bin\\"); +_LIT(KSystemAgentName, "z:\\sys\\bin\\SysAgt2Svr.exe"); +_LIT(KLitLocaleData,"?:\\System\\Data\\LOCALE.D"); +_LIT(KLocaleDllNameBase, "ELOCL"); +_LIT(KLocalDriveMappingFile,"Z:\\SYS\\DATA\\ESTART.TXT"); +_LIT(KWindowServerRootName1,"EWSRV.EXE"); +_LIT(KSystemStarterName, "z:\\sys\\bin\\SYSSTART.EXE"); +_LIT(KSystemStateManager, "z:\\sys\\bin\\SYSSTATEMGR.EXE"); + +//const TInt KPatchLddUidValue=0x100000cc; // patch ldds should specify this as their third uid + +GLDEF_D TBool gMountRofsAlone=ETrue; +GLDEF_D TBool gMountComposite=EFalse; + +enum TCompositeMountSate + { + ENoMounts, + EHasMounts, + ESwapped + }; + +LOCAL_D TCompositeMountSate gCompositeMountState=ENoMounts; + +#if !defined(AUTODETECT_DISABLE) +LOCAL_D TInt gNCompositeMounts=0; +#endif + +#if defined(__EPOC32__) && defined(__X86__) +LOCAL_D TInt gNFloppies=0; +#endif + +/** +ASCII text file reader constructor +*/ +TText8FileReader::TText8FileReader() + { + + iBufPos=-1; + iFileDataBuf=NULL; + iFileSize=0; + } + +/** +ASCII text file reader desctructor +*/ +TText8FileReader::~TText8FileReader() + { + + delete[] iFileDataBuf; + } + +/** +Supply an ASCII text file for the file reader. +This function reads the entire contents of this file into a buffer, converting to +unicode / folding each character. Subsequent parsing of the file data is all done from this +buffer. +@param aFile The file to be read. Must already be opened for read access in EFileStreamText mode. +@return KErrNone if no error. +*/ +TInt TText8FileReader::Set(RFile& aFile) + { + + iFile=aFile; + iBuf.Zero(); + iBufPos=0; + + // Read the size of the file + TInt r=iFile.Size(iFileSize); + if (r!=KErrNone || !iFileSize) + return(KErrGeneral); + + // Allocate a buffer to read in the file + iFileDataBuf=new TText[iFileSize+1]; // +1 in case need to NULL terminate the end of the last string + if (iFileDataBuf==NULL) + return(KErrNoMemory); + + // Read the entire contents of the file into the buffer + TPtr fdata(NULL,0); + TInt pos=0; + r=iFile.Seek(ESeekStart,pos); + while (pos data; + if( file.Read(data) == KErrNone && data.Size()==sizeof(TLocData)) + { + data().iLocale.Set(); + TInt offset = data().iLocale.UniversalTimeOffset().Int(); + if (data().iLocale.QueryHomeHasDaylightSavingOn()) + offset += 3600; + User::SetUTCOffset(offset); + User::SetCurrencySymbol(data().iCurrency); + } + file.Close(); + } + return(KErrNone); + } + + +/** +Load the Locale DLL +@return KErrNone if successful. + KErrNotFound if locale DLL not found. + Or other system wide error code. +*/ +TInt LoadLocaleDll() + { + TBuf<16> localeDllName; + + TInt languageIndex; + TInt error=HAL::Get(HALData::ELanguageIndex,languageIndex); + if (error!=KErrNone) + error = KErrNotFound; + else + { + TBuf<6> extension; // Dot plus five digit locale + _LIT(KExtension,".%u"); + extension.Format(KExtension, languageIndex); + if (extension.Length()<3) // Padd ".1" to ".01" for compatibility. + { + _LIT(KPadding,"0"); + extension.Insert(1,KPadding); + } + localeDllName=KLocaleDllNameBase; + localeDllName.Append(extension); + error = UserSvr::ChangeLocale(localeDllName); + } + if (error==KErrNotFound) + { + // Try default locale + _LIT(KLocaleDllNameExtension, ".LOC"); + localeDllName=KLocaleDllNameBase; + localeDllName.Append(KLocaleDllNameExtension); + error = UserSvr::ChangeLocale(localeDllName); + } + if (error == KErrNone) + TLocale().Set(); + return error; + } + +/** +Initialise the HAL. +Search for a saved HAL file - containing a series of saved HAL attributes. +If found, initialise each attribute saved. + +@return KErrNone if successful; KErrGeneral if the exe panicked. +*/ +TInt TFSStartup::InitialiseHAL() + { + RProcess process; + TInt result = process.Create(_L("HALSettings.exe"), _L("INITIALISE")); + if(result != KErrNone) + return result; + TRequestStatus status; + process.Logon(status); + if (status != KRequestPending) + process.Kill(0); // abort + else + process.Resume(); // logon OK + User::WaitForRequest(status); + + // Special case to ensure the nonsecure clock offset set function gets called + TInt nsc_offset = 0; + result = HAL::Get(HAL::ETimeNonSecureOffset,nsc_offset); + if (result == KErrNone) + { + HAL::Set(HAL::ETimeNonSecureOffset,nsc_offset); // this will only succeed when hal.dat is missing and the function wasnt called by halsettings.exe + } + + + // we can't use the 'exit reason' if the exe panicked as this + // is the panic 'reason' and may be '0' which cannot be distinguished + // from KErrNone + result = process.ExitType() == EExitPanic ? KErrGeneral : status.Int(); + process.Close(); + return result; + } + +/** +Create and resume a server. Start without specifying a path. +If this fails, then systematically try to start it from +each valid drive in turn (Y: - A:, then Z:). +The second phase is to handle the sitation where a version +of the executable is found on a drive early in the search order +(e.g. C:) - that fails to load. Rather than failing the load +on the 1st error, this function keeps going through all the valid drives. + +@param aDrives The drive list, to determine which are valid. +@param aRootName The root name of the executable. + +@return ETrue if the server was eventually created successfully, EFalse if not. +*/ +TBool TFSStartup::CreateServer(const TDriveList& aDrives, const TDesC& aRootName) + { + RProcess ws; + TInt r=ws.Create(aRootName, KNullDesC); + if (r!=KErrNone) + { + TFileName name; + name = KServerPathSysBin(); + name+=aRootName; + TInt i=EDriveZ; + FOREVER + { + i= (i==0) ? EDriveZ : i-1; + if (aDrives[i]!=KDriveAbsent) // Got a valid drive + { + name[0]=(TText)('A'+i); // Set the drive letter + r=ws.Create(name,KNullDesC); + if (r==KErrNone) + break; + } + if (i==EDriveZ) + return EFalse; + } + } + ws.Resume(); + ws.Close(); + return ETrue; + } + +#ifdef AUTO_PROFILE +_LIT(KProfilerName,"profiler.exe"); +_LIT(KProfilerCmd,"start"); +/** +Start the profiler +*/ +void TFSStartup::StartProfiler() + { + RProcess p; + TInt r=p.Create(KProfilerName,KProfilerCmd); + if (r==KErrNone) + { + p.Resume(); + p.Close(); + } + } +#endif + +#if !defined(AUTODETECT_DISABLE) +/** +FSY detection function for the local FSY (assumed to be FAT). This will return success for MMC, +ATA, Floppy and IRAM devices that are FAT formatted. Will also return success for any drive +(other than those designated for CD ROMs) which isn't ready - assuming these to be removable FAT +formatted devices. For floppy devices detected on the X86 build, we need to change the drive +mapping so that these are mounted on drives A: or B:. +*/ +GLDEF_C TInt DetectELocal(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + TInt socknum; + if (cr==KErrNotReady && caps.iType != EMediaCdRom) + { +#if defined(__EPOC32__) && defined(__X86__) + // For FDD iEraseBlockSize top 16 bits is sectors per track + if (caps.iType==EMediaFloppy && (caps.iEraseBlockSize>>16)) + { +pc_floppy: + if (gNFloppies < 2) + { + // Change the default mapping to A: or B: + TInt ret = gNFloppies ? EDriveB : EDriveA; + ++gNFloppies; + return KFsDetectMappingChangeReturnOffset + ret; + } + return KErrNone; + } +#endif + return KErrNone; // Removable and not ready - assume fat + } + if(cr == KErrCorrupt && ld.IsRemovable(socknum)) // Removable and media corrupt - assume fat + { + return KErrNone; + } + if (caps.iType!=EMediaFloppy && caps.iType!=EMediaHardDisk) + return KErrGeneral; + if (cr==KErrNone && (PartitionIsFAT32(caps.iPartitionType) || PartitionIsFAT(caps.iPartitionType)) ) + { +#if defined(__EPOC32__) && defined(__X86__) + if (cr!=KErrNotSupported && caps.iType==EMediaFloppy && (caps.iEraseBlockSize>>16)) + goto pc_floppy; +#endif + return KErrNone; + } + return KErrGeneral; + } + +/** +FSY detection function for the local FSY (assumed to be FAT) running over internal RAM. This will +return success for any drive containing RAM media which reports a FAT16 partition type. +*/ +GLDEF_C TInt DetectIRam(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType==EMediaRam && caps.iPartitionType==KPartitionTypeFAT16) + return KErrNone; + return KErrGeneral; + } + +/** +FSY detection function for the local FSY (assumed to be FAT) running over a NAND FTL. This will +return success for any drive containing NAND media which reports a FAT16 partition type. +*/ +GLDEF_C TInt DetectFtl(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType==EMediaNANDFlash && caps.iPartitionType==KPartitionTypeFAT16) + return KErrNone; + return KErrGeneral; + } + +/** +FSY detection function for the ROFS FSY. This will return success for any drive containing NAND +media which reports a ROFS partition type as long as the ROFS FSY is present - but not the Composite FSY +*/ +GLDEF_C TInt DetectRofs(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if ((caps.iType==EMediaNANDFlash) && caps.iPartitionType==KPartitionTypeRofs && gMountRofsAlone) + return KErrNone; + return KErrGeneral; + } + +/** +FSY detection function for the Composite FSY. This will return success for the 1st drive containing NAND +media which reports a ROFS partition type as long as both the ROFS and Composite FSYs are present. We +change the DRIVE mapping so that this is mounted on drive Z:. Any subsequent ROFS partitions detected +can be mounted as ROFS. +*/ +GLDEF_C TInt DetectComposite(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if ((caps.iType==EMediaNANDFlash) && caps.iPartitionType==KPartitionTypeRofs && gMountComposite) + { + if (!gNCompositeMounts) + { + gNCompositeMounts++; + gMountRofsAlone=ETrue; // Any further ROFS drives found can be mounted as such + return(KFsDetectMappingChangeReturnOffset+EDriveZ); + } + } + return KErrGeneral; + } + +/** +FSY detection function for the LFFS FSY. This will return success for any drive containing NOR +media which reports an LFFS partition type. +*/ +GLDEF_C TInt DetectEneaLFFS(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType==EMediaFlash && caps.iPartitionType==KPartitionTypeEneaLFFS) + return KErrNone; + return KErrGeneral; + } + +/** +FSY detection function for the ISO 9660 FSY (X86 only). This will return success for CD ROM +devices. +*/ +GLDEF_C TInt DetectIso9660(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType == EMediaCdRom) + return KErrNone; + return KErrGeneral; + } + +/** +FSY detection function for the NTFS FSY (X86 only). This will return success for any drive +containing a hard disk device which reports an NTFS partition type. +*/ +GLDEF_C TInt DetectNtfs(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps) + { + (void)ld; + (void)cr; + if (caps.iType==EMediaHardDisk && PartitionIsNTFS(caps.iPartitionType)) + return KErrNone; + return KErrGeneral; + } +#endif + +/** +Format a drive. + +@param aDrive The number of the drive to be formatted (0-25). + +@return KErrNone if no error otherwise one of the other system wide error codes. +*/ +TInt TFSStartup::FormatDrive(TInt aDrive) + { + TBuf<2> driveName(_S("A:")); + driveName[0] = (TText)(aDrive+'A'); + RFormat format; + TInt count; + TInt d = format.Open(iFs, driveName, EHighDensity, count); + DEBUGPRINT2("FormatOpen %S -> %d", &driveName, d); + if(d!=KErrNone) + return d; + ShowFormatProgress(count, aDrive); +#ifdef _DEBUG + TInt lastCount = -1; +#endif + while (d==KErrNone && count) + { +#ifdef _DEBUG + if (lastCount != count) + DEBUGPRINT1("Format count %d", count); + lastCount = count; +#endif + d=format.Next(count); + ShowFormatProgress(count, aDrive); + } + format.Close(); + DEBUGPRINT1("Format complete %d", d); + return d; + } + +/** +Set System Drive if defined either in ESTART.TXT or in HALData::ESystemDrive +*/ +void TFSStartup::SetSystemDrive() + { + DEBUGPRINT("TFSStartup::SetSystemDrive"); + for(TInt i=0; i= EDriveA && drive <= EDriveZ) + { + err = iFs.SetSystemDrive((TDriveNumber)drive); + DEBUGPRINT2("SetSystemDrive from HAL %d, err:%d", drive, err); + __ASSERT_ALWAYS(err==KErrNone || err==KErrAlreadyExists, Panic(ESetSystemDriveFail, err)); + } + } + + +/** +Parse the flags field of a drive mapping record that has been read from the drive mapping file. +The flags field text is expected to contain one or more flags, each delimited with a "," char. +Override this function to support custom drive configuation flags. + +@param aFlagDesc Non-modifiable descriptor holding the flags record text to be parsed. +@param aFlagVar An integer to hold the returned flag settings. +@param aSpare An integer to hold any additional info returned. + +@return Always returns KErrNone (but derived version may not). +*/ +TInt TFSStartup::ParseMappingFileFlags(const TPtrC& aFlagDesc,TUint32& aFlagVar,TInt& aSpare) + { + + TInt r=KErrNone; + TInt pos=0; + TInt len; + TPtrC ptr; + TBool endOfFlagDesc=EFalse; + aFlagVar=0; + while (!endOfFlagDesc && r==KErrNone) + { + ptr.Set(aFlagDesc.Mid(pos)); + len=ptr.Locate(','); + if (len==KErrNotFound) + endOfFlagDesc=ETrue; + else + { + ptr.Set(ptr.Left(len)); + pos+=(len+1); + } + if (ptr.MatchF(_L("FS_FORMAT_ALWAYS"))!=KErrNotFound) + aFlagVar|=FS_FORMAT_ALWAYS; + else if (ptr.MatchF(_L("FS_FORMAT_COLD"))!=KErrNotFound) + aFlagVar|=FS_FORMAT_COLD; + else if (ptr.MatchF(_L("FS_FORMAT_CORRUPT"))!=KErrNotFound) + aFlagVar|=FS_FORMAT_CORRUPT; + else if (ptr.MatchF(_L("FS_DISMNT_CORRUPT"))!=KErrNotFound) + aFlagVar|=FS_DISMNT_CORRUPT; + else if (ptr.MatchF(_L("FS_SWAP_CORRUPT*"))!=KErrNotFound) + { + len=ptr.Locate('-'); + if (iFs.CharToDrive(ptr[len+1],aSpare)==KErrNone && iDriveSwapCount==0) // We only allow one swap + { + aFlagVar|=FS_SWAP_CORRUPT; + iDriveSwapCount++; + } + } + else if (ptr.MatchF(_L("FS_SYNC_DRIVE"))!=KErrNotFound) + aFlagVar|=FS_SYNC_DRIVE; + else if (ptr.MatchF(_L("FS_SCANDRIVE"))!=KErrNotFound) + aFlagVar|=FS_SCANDRIVE; + else if (ptr.MatchF(_L("FS_COMPOSITE"))!=KErrNotFound) + aFlagVar|=FS_COMPOSITE; + else if (ptr.MatchF(_L("FS_NO_MOUNT"))!=KErrNotFound) + aFlagVar|=FS_NO_MOUNT; + else if (ptr.MatchF(_L("FS_ALLOW_REM_ACC"))!=KErrNotFound) + aFlagVar|=FS_ALLOW_REM_ACC; + else if (ptr.MatchF(_L("FS_NOT_RUGGED")) != KErrNotFound) + aFlagVar |= FS_NOT_RUGGED; + else if (ptr.MatchF(_L("FS_SYSTEM_DRIVE")) != KErrNotFound) + aFlagVar |= FS_SYSTEM_DRIVE; + else + r=ParseCustomMountFlags(&ptr,aFlagVar,aSpare); + } + return(r); + } + +/** +Parse for custom mount flags - default implementation. +In either the auto-configuration scheme or the drive mapping file scheme, +to add support for additional mount flags, this function needs to be override. + +@param aFlagPtr The flag text. +@param aFlags An integer to hold the returned mount flag settings +@param aSpare An integer to hold any additional info returned. + +@return KErrNone if no error. +*/ +TInt TFSStartup::ParseCustomMountFlags(TPtrC* /*aFlagPtr*/,TUint32& /*aFlags*/,TInt& /*aSpare*/) + { + + return(KErrNone); + } + +/** +Process any custom mount flags - default implementation. +In either the auto-configuration scheme or the drive mapping file scheme, +to add support for additional mount flags, this function needs to be override. + +@param aMountRet The value returned when attempting to mount the drive. +@param aFlags The mount flags. +@param aSpare An integer containing any additional info associated with the flags. +@param aDrive The drive number. + +@return KErrNone if no error. +*/ +TInt TFSStartup::HandleCustomMountFlags(TInt& /*aMountRet*/,TInt& /*aFlags*/,TInt& /*aSpare*/,TInt /*aDrive*/) + { + + return(KErrNone); + } + +/** +Process the local drive field of a drive mapping record + +@param aDriveDesc The comma seperated local drives +@param aDrives An array of drive numbers (return reference) +@param aCount The number of local drives found. + +@return KErrNone if no error, otherwise a System-wide error code. +*/ +TInt TFSStartup::ParseMappingFileLocalDrive(const TPtrC& aDriveDesc,TUint32 (&aDrives)[KMaxLocalDrives],TInt& aCount) + { + + TInt len; + TInt pos=0; + TPtrC ptr; + TBool endOfDriveDesc=EFalse; + TInt err = KErrNone; + aCount=0; + while (!endOfDriveDesc) + { + ptr.Set(aDriveDesc.Mid(pos)); + len=ptr.Locate(','); + if (len==KErrNotFound) + endOfDriveDesc=ETrue; + else + { + ptr.Set(ptr.Left(len)); + pos+=(len+1); + } + // Get numeric value + TLex lex; + lex.Assign(ptr); + lex.SkipSpace(); + TUint32 locDrvNum; + if (lex.BoundedVal(locDrvNum,EDecimal,(KMaxLocalDrives-1))!=KErrNone) + return(KErrArgument); + // Store + if(aCount >= KMaxLocalDrives) + return KErrOverflow; + aDrives[aCount]=locDrvNum; + ++aCount; + } + return err; + } + + +/** +Parse a drive mapping record that has been read from the drive mapping file. + +@param aTextLine Modifiable ptr descriptor holding the mapping record text + to be parsed. Note that this function will null-terminate + any FSY or extension names it detects. This will generally + result in the over-writing of the field separator or end of + record delimitor but consideration is required where a + mapping file ends with such a string. +@param anInfo A stucture to hold the returned mapping settings, + FSY/ext name string pointers and mounting flags. + +@return KErrNone if record is successfully parsed and 'anInfo' contains + mapping info to be applied. + KErrNotFound if the record is a comment line. + KErrArgument if the syntax of record is incorrect. +*/ +TInt TFSStartup::ParseMappingRecord(TPtr& aTextLine,SLocalDriveMappingInfo& anInfo) + { + TPtrC token; + TLex lex(aTextLine); + + TInt driveNumber = KDriveInvalid; + TUint32 localDriveNums[KMaxLocalDrives]; + const TText* fsyName = NULL; + const TText* objName = NULL; + const TText* extName = NULL; + TUint32 flags = 0; + TInt spare = 0; + + // Get all of the above Attributes. + + + token.Set(lex.NextToken()); + if (token.Length() <= 1 || token[0]=='#') // Blank line or comment line + return(KErrNotFound); + + // Drive number + if (token[1]!=':' || iFs.CharToDrive(token[0],driveNumber)!=KErrNone) + return(KErrArgument); + + // Local drive number(s) + lex.SkipSpace(); + token.Set(lex.NextToken()); + TInt localDriveCount = 0; + TInt err = ParseMappingFileLocalDrive(token,localDriveNums,localDriveCount); + if(err != KErrNone) + { + return err; + } + if(localDriveCount==0) + { + return KErrArgument; + } + + TInt tokLen; + TPtr fileName(NULL,0); + TBool endOfRecord = EFalse; + + // .FSY file name + token.Set(lex.NextToken()); + if (!endOfRecord && (token.Length()==0 || token[0]=='#')) + endOfRecord = ETrue; + else + { + if (token[0]!='0') + { + tokLen=token.Length(); + fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1); + token.Set(lex.NextToken()); + fsyName=fileName.PtrZ(); + } + else + { + token.Set(lex.NextToken()); + } + } + + // Object name of .FSY + if (!endOfRecord && (token.Length()==0 || token[0]=='#')) + { + endOfRecord = ETrue; + } + else // Get FSY + { + if (token[0]!='0') + { + tokLen=token.Length(); + fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1); + token.Set(lex.NextToken()); + objName=fileName.PtrZ(); + } + else + { + token.Set(lex.NextToken()); + } + } + + // Extension name + if (!endOfRecord && (token.Length()==0 || token[0]=='#')) + { + endOfRecord = ETrue; + } + else // Get extension + { + if (token[0]!='0') + { + tokLen=token.Length(); + fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1); + token.Set(lex.NextToken()); + extName=fileName.PtrZ(); + } + else + { + token.Set(lex.NextToken()); + } + } + + // Flags + if (!endOfRecord && (token.Length()==0 || token[0]=='#')) + { + endOfRecord = ETrue; + } + else // Get Flags + { + if (token[0]!='0') + { + TInt r=ParseMappingFileFlags(token,flags,spare); + if(r!=KErrNone) + return r; + } + } + + // + // For every local drive + // + SLocalDriveMappingInfo* mappingInfo = &anInfo; + for(TInt i = 0; i= KMaxLocalDrives) + return KErrOverflow; + Mem::FillZ(mappingInfo,sizeof(SLocalDriveMappingInfo)); + + mappingInfo->iDriveNumber = driveNumber; + mappingInfo->iLocalDriveNumber = localDriveNums[i]; + mappingInfo->iFsInfo.iExtName = extName; + mappingInfo->iFsInfo.iFsyName = fsyName; + mappingInfo->iFsInfo.iObjName = objName; + mappingInfo->iSpare = spare; + mappingInfo->iFsInfo.iFlags = flags; + + // If there was more than 1 local drive number (multi-slot device) + // then increase iMapCount so that the mappingInfo doesn't get + // clobbered next time this function is called. + if(i>=1 && ((TInt)localDriveNums[i])!=KDriveInvalid) + { + iMapCount++; + DEBUGPRINT2("Alternative Entry found for registered ldrive:%d -> %c:",localDriveNums[i],(mappingInfo->iDriveNumber+'A')); + } + mappingInfo++; + } + return KErrNone; + } + +/** +This is only called if a mapping configuration has specified "FS_SWAP_CORRUPT". +If it is necessary to implement the drive swap then it is required that +the entry for the second drive involved in the swap (ie the one specified +in "FS_SWAP_CORRUPT-") occurs later in the mapping array than the one +specifying the swap. This functions checks whether the ordering is OK and +swaps the entries for the two drives if necessary. + +@param aTotalEntries The total number of valid entries in the mapping array. +*/ +void TFSStartup::CheckAndReOrderArrayForSwapping(TInt aTotalEntries) + { + + // Find the swapper - and determine its entry number + TInt i; + for (i=0;iswappeeEntryNo) + { + SLocalDriveMappingInfo tmp; + tmp=iDriveMappingInfo[swapperEntryNo]; + iDriveMappingInfo[swapperEntryNo]=iDriveMappingInfo[swappeeEntryNo]; + iDriveMappingInfo[swappeeEntryNo]=tmp; + } + } + +/** +Swap the local drive mappings of two entries in the mapping array. Also, update the local drive mapping previously +written to the file server. + +@param aCurrentEntry The position in the mapping array of the next mapping to be applied. + This coincides with the drive which has 'requested' the swap. + (The other mapping involved in the swap is guarenteed to be later + in the list and therefore not yet applied). +@param aTotalEntries The total number of valid entries in the mapping array. + +@panic ESTART_12 0; If swap mapping file array is inconsistent. +*/ +void TFSStartup::SwapDriveMappings(TInt aCurrentEntry,TInt aTotalEntries) + { + DEBUGPRINT1("TFSStartup::SwapDriveMappings - Index %d",aCurrentEntry); + TInt firstDrive=iDriveMappingInfo[aCurrentEntry].iDriveNumber; + TInt secondDrive=iDriveMappingInfo[aCurrentEntry].iSpare; + + // Find the entry for the other mapping that we need to swap with + TInt secondEntry; + for (secondEntry=aCurrentEntry ; secondEntry %d", &mappingFileName, r); + if (r == KErrNone) + { + // pass ROM address of estart.txt file to file server to allow it to support + // reading of ".ini file" - style parameters + TInt romAddress = 0; + r = f.Seek(ESeekAddress, romAddress); + if(r == KErrNone) + { + TInt size = 0; + r = f.Size(size); + if (r == KErrNone) + { + if(size > 0) + { + TPtrC8 ptr((TUint8*)romAddress, size); + iFs.InitialisePropertiesFile(ptr); + } + else + { + r = KErrGeneral; + } + } + } + } + // If any error detected found, the default version of RFs::InitialisePropertiesFile() + // will be called before exiting. + if (r!=KErrNone) + { + TPtrC8 ptr(0, 0); + iFs.InitialisePropertiesFile(ptr); + return(r); + } + + + + // Create a mapping file reader and pass it the file object. This will also result in the copying of the contents of + // the file into reader's buffer. Mapping information read from the file will include pointers to text strings in + // this buffer and so the reader object must not be deleted until processing is complete. + iMapFile = new TText8FileReader; + if (!iMapFile) + { + f.Close(); + return(KErrNoMemory); + } + r=iMapFile->Set(f); + DEBUGPRINT1("Reading map file returns %d",r); + f.Close(); // Can't leave file on Z: open too long because can't mount composite FSY on Z: in this sitaution + if (r!=KErrNone) + return(r); + + // Parse each drive mapping record in turn, saving the information in an array of mapping structures - one for + // each valid record. + + TPtr linePtr(NULL,0); + iMapCount=0; + SLocalDriveMappingInfo* infoPtr; + while ((r=iMapFile->Read(linePtr))==KErrNone && iMapCountiLocalDriveNumber; + __ASSERT_DEBUG(localDriveNumber >=0 && localDriveNumber < KMaxLocalDrives, User::Invariant()); + if (iLocalDriveList[localDriveNumber]!=KDriveInvalid) + { + DEBUGPRINT2("Entry found for registered ldrive:%d -> %c:",localDriveNumber,(infoPtr->iDriveNumber+'A')); + iMapCount++; + } + else + { + DEBUGPRINT1("Invalid LocalDriveNumber : %d",localDriveNumber); + } + } + else + { + infoPtr->iLocalDriveNumber = KDriveInvalid; // reset all local drives + } + } + + if (r!=KErrEof) + { + return((r==KErrNone)?KErrGeneral:r); // Error reading the records, or too many records in mapping file + } + + // If there is the potential of a drive swap then check that the order of the entries in the mapping array + // are consitent for this - re-order if necessary + if (iDriveSwapCount) + CheckAndReOrderArrayForSwapping(iMapCount); + + // Scan through the array of valid mappings - updating the the local drive list. Once, complete, write the list + // to the File Server. (Apart from swapping internal drives, this can only be written once). + TInt firstComp=-1; + + // first clear default mappings for all local drives not listed on mapping file + TInt i; + for(i=0;iiRemovable = EFalse; + r = drive.Connect(iDriveMappingInfo[i].iLocalDriveNumber, changed); + if (r == KErrNone) + { + infoPtr->iCapsRetCode = r = drive.Caps(caps); + if (r==KErrNone && caps().iDriveAtt&KDriveAttRemovable) + { + infoPtr->iRemovable = ETrue; + drive.Disconnect(); + continue; + } + drive.Disconnect(); + } + + r=MountFileSystem(iDriveMappingInfo[i]); + if (r==KErrDisMounted) + { + // We have encountered a corrupt internal drive which should be swapped with another internal drive + SwapDriveMappings(i,iMapCount); + i--; // Re-attempt to mount the same drive now that the mappings are swapped + } + + // If the drive is pageable, search for a ROM image file name and if found clamp it + // so that nothing can overwrite it + DEBUGPRINT3("Testing if Drive %c is pageable, r %d att %08X", 'A' + iDriveMappingInfo[i].iDriveNumber, r, caps().iMediaAtt); + if (r == KErrNone && (caps().iMediaAtt & KMediaAttPageable)) + { + RFile file; + RArray sysFiles; + r = SysFileNames(sysFiles); + TInt sysFilesCount = sysFiles.Count(); + + for (TInt n=0; n< sysFilesCount; n++) + { + TFileName romFilePath; + romFilePath.Append( (TText) ('A'+iDriveMappingInfo[i].iDriveNumber) ); + romFilePath.Append(':'); + romFilePath.Append(sysFiles[n]); + + DEBUGPRINT1("Drive %c is pageable", 'A' + iDriveMappingInfo[i].iDriveNumber); + + r = file.Open(iFs, romFilePath, EFileRead); + DEBUGPRINT2("Opening %S returned %d", &romFilePath, r); + if (r == KErrNone) + { + RFileClamp handle; + r = handle.Clamp(file); + DEBUGPRINT2("Clamping %S returned %d", &romFilePath, r); + file.Close(); + } + } + sysFiles.Close(); + } + + } + if (gCompositeMountState==1) + LoadCompositeFileSystem(firstComp); + + return(KErrNone); + } + + +/** +Return the filenames of any "System" files on a writable drive (e.g internal MMC). +If the files are found, then they are clamped (and never unclamped) to prevent them from being overridden. +This function should be overriden by the variant if needed. + +@return KErrNotSupported, by default if the function is not overridden. +*/ +TInt TFSStartup::SysFileNames(RArray& /*aFileNames*/) + { + return KErrNotSupported; + } + +/** +Search for any unused drive number that has not been added to the list. + +@param aDrvNum Drive number to be checked, if used or not. + +@return KErrNone if found one unused drive; KErrOverflow if all drives are used. +*/ +TInt TFSStartup::SearchForUnusedDriveNumber(TInt& aDrvNum) + { + TInt i; + while(++aDrvNum<=(TInt)EDriveZ) + { + for(i=0;i %d",&fsyname,r); + if (r!=KErrNone && r!=KErrAlreadyExists) + return(r); + + if (flags & FS_NOT_RUGGED) + { + r = iFs.SetStartupConfiguration(ESetRugged, (TAny*)drive, (TAny*)EFalse); + iRuggedFileSystem = 0; + } + + objname.Set((anInfo.iFsInfo.iObjName) ? anInfo.iFsInfo.iObjName : anInfo.iFsInfo.iFsyName); + TBool isSync=(flags & FS_SYNC_DRIVE); + if (anInfo.iFsInfo.iExtName) + { + TPtrC extname(anInfo.iFsInfo.iExtName); + r=iFs.AddExtension(extname); + if (r==KErrNone || r==KErrAlreadyExists) + r=iFs.MountFileSystem(objname,extname,drive,isSync); + } + else + r=iFs.MountFileSystem(objname,drive,isSync); + + DEBUGPRINT4("MountFileSystem(%S) on drive %c: -> %d (sync=%d)",&objname,(drive+'A'),r,isSync); + iUnmountedDriveBitmask&=~(0x01<<(anInfo.iLocalDriveNumber)); + } + + // Process the mount flags + DEBUGPRINT1("FSI flags %08x",flags); + TInt cf; + if ((cf=HandleCustomMountFlags(r,flags,anInfo.iSpare,drive))!=KErrNone) + return(cf); + + if (flags & FS_COMPOSITE) + if (anInfo.iFsInfo.iFsyName && TPtrC(anInfo.iFsInfo.iFsyName).CompareF(KEcomp)) + LoadCompositeFileSystem(anInfo); + else + LoadCompositeFileSystem(drive); + // Handle format related flags + if (flags & FS_FORMAT_ALWAYS) + r=FormatDrive(drive); + if ((flags & FS_FORMAT_COLD) && iColdStart) + r=FormatDrive(drive); + if (r==KErrCorrupt && (flags & FS_FORMAT_CORRUPT)) + r=FormatDrive(drive); + + + //-- running ScanDrive on Rugged FAT volumes. "Rugged FAT" and "ScanDrive" are counterparts. + //-- 1. Having "Rugged FAT" volume and not running ScanDrive on it doesn't make any sense and dangerous because "Rugged FAT" mechanisms imply using ScanDrive + //-- 2. Vice versa, running ScanDrive on "non-rugged FAT" doesn't make any sense, it is jsut waste of time. + //-- Thus: if the volume is detected as "Rugged FAT", force running ScanDrive on it; otherwise ignore FS_SCANDRIVE flag +#if !defined(__X86__) + if(r==KErrNone) + { + TText driveLetter=(TText)(drive+'A'); + TBuf<3> driveDes=_L("?:\\"); + driveDes[0]=driveLetter; + + if(iRuggedFileSystem) + {//-- the volume has rugged FAT, force ScanDrive + + if(!(flags & FS_SCANDRIVE)) + {//-- no FS_SCANDRIVE flag, this is obvious misconfiguration + if(objname.CompareF(_L("FAT")) == 0) + { + DEBUGPRINT1("### !!!! WARNING!!! Drive %S has RuggedFAT, but no FS_SCANDRIVE flag in estart.txt", &driveDes); + DEBUGPRINT( "### !!!! Forcing ScanDrive. Check that the drive is configured properly !!!"); + } + } + + iFs.ScanDrive(driveDes); + } + else + {//-- the volume doesn't have rugged FAT + if(flags & FS_SCANDRIVE) + {//-- FS_SCANDRIVE flag is set for non-rugged-FAT drive. don't run ScanDrive + DEBUGPRINT1("### !!!! WARNING!!! Drive %S has NON-Rugged FAT, but FS_SCANDRIVE flag is set in estart.txt", &driveDes); + DEBUGPRINT( "### !!!! SKipping ScanDrive. Check that the drive is configured properly !!!"); + } + } + } + +#endif + + // Handle swap on corrupt or dismount on corrupt + if (r==KErrCorrupt && ((flags & FS_DISMNT_CORRUPT) || (flags & FS_SWAP_CORRUPT))) +// if (((flags & FS_DISMNT_CORRUPT) || (flags & FS_SWAP_CORRUPT))) // Testing swap mode - always swaps + { + if (objname.Ptr()) + iFs.DismountFileSystem(objname,drive); + + if (flags & FS_SWAP_CORRUPT) + { + anInfo.iFsInfo.iFlags&=~FS_SWAP_CORRUPT; // Mustn't try to swap again the next time + r=KErrDisMounted; // Signal that this needs to be re-mounted on another drive + } + } + return(r); + } + +#if !defined(AUTODETECT_DISABLE) +const TInt KMaxFSInfoTableEntries=8; +/** +Standard file system info. array - used when auto-detecting an appropraite FSY for a local drive. In this scheme, the local +drive capabilities and partition type information is examined to determine an appropraite FSY for the drive. Each entry +contains an FSY detection function together with the corresponding information for that particular FSY configuration. This +information includes the FSY/ext name string pointers and mounting flags. Each detection function should uniquely identify +its associated FSY configuration. +*/ +LOCAL_D const SFileSystemInfo FileSystems[KMaxFSInfoTableEntries] = + { + {DetectELocal, {_S("elocal"), _S("fat"), 0, FS_SCANDRIVE}}, + {DetectIRam, {_S("elocal"), _S("fat"), 0, FS_FORMAT_COLD|FS_SYNC_DRIVE}}, + {DetectFtl, {_S("elocal"), _S("fat"), 0, FS_FORMAT_CORRUPT|FS_SCANDRIVE}}, + {DetectRofs, {_S("erofs"), _S("rofs"), 0, FS_DISMNT_CORRUPT}}, + {DetectComposite, {0, 0, 0, FS_COMPOSITE}}, + {DetectEneaLFFS, {_S("elffs"), _S("lffs"), 0, FS_FORMAT_CORRUPT}}, + {DetectIso9660, {_S("iso9660"), 0, 0, 0}}, + {DetectNtfs, {_S("ntfs"), 0, 0, 0}}, + }; + +/** +Return the next entry from the standard file system info array - used when auto-detecting an FSY for a local drive. +Override this function when altering or extending the standard file system info. array. + +@param anInfo Address of a pointer to a stucture to hold the returned mapping settings, + FSY/ext name string pointers and mounting flags. +@param aPos The current position within the array. The caller is responsible to + initializing and incrementing this. + +@return KErrNone if no error, KErrNotFound if the end of the array is reached. +*/ +TInt TFSStartup::GetNextStandardFSInfoEntry(const SFileSystemInfo** anEntry,TInt aPos) + { + + if (aPos capsBuf(caps); + RLocalDrive ld; + TBool changed; + TInt r = ld.Connect(aLocalDriveNumber, changed); + DEBUGPRINT1("Connect -> %d", r); + if (r!=KErrNone) + return(r); + TInt cr=ld.Caps(capsBuf); + DEBUGPRINT1("Caps -> %d", cr); + const SFileSystemInfo* fsi=NULL; + for (TInt i=0 ; (r=GetNextStandardFSInfoEntry(&fsi,i))==KErrNone ; i++) + { + TInt d=(*fsi->iDetect)(ld,cr,caps); + DEBUGPRINT2("FS:%d Detect -> %d",i,d); + if (dKErrNone) + { + d-=KFsDetectMappingChangeReturnOffset; + if (d>=EDriveA && d<=EDriveZ) + iLocalDriveList[aLocalDriveNumber]=d; + } + TInt drive=iLocalDriveList[aLocalDriveNumber]; + anInfo.iDriveNumber=drive; + anInfo.iLocalDriveNumber=aLocalDriveNumber; + anInfo.iFsInfo=fsi->iFsInfo; + anInfo.iSpare=0; + break; + } + ld.Close(); + return(r); + } + +/** +For each registered local drive on the system detect an appropriate FSY configuration +and attempt to mount this on the drive concerned. + +@return Always returns KErrNone. +*/ +TInt TFSStartup::DetectAndMountFileSystems() + { + + InitCompositeFileSystem(); + + // Determine an appropriate FSY configuration for each registered local drive + TInt i; + DEBUGPRINT("DetectAndMountFileSystems"); + iMapCount=0; + SLocalDriveMappingInfo* infoPtr; + for (i=0;i%c: (%s)",i,(infoPtr->iDriveNumber+'A'),infoPtr->iFsInfo.iFsyName); + iMapCount++; + } + } + } + + // Scan through the array of valid mappings - updating the the local drive list. Once, complete, write the list + // to the File Server (can only be written once). + for (i=0;iiRemovable = EFalse; + TInt r = drive.Connect(iDriveMappingInfo[i].iLocalDriveNumber, changed); + if (r == KErrNone) + { + infoPtr->iCapsRetCode = r = drive.Caps(caps); + TInt sockNum; + if (r==KErrNone && (caps().iDriveAtt&KDriveAttRemovable || drive.IsRemovable(sockNum))) + { + infoPtr->iRemovable = ETrue; + drive.Disconnect(); + continue; + } + drive.Disconnect(); + } + + r=MountFileSystem(iDriveMappingInfo[i]); + if (r==KErrDisMounted) + { + // We have encountered a corrupt internal drive which should be swapped with another internal drive + SwapDriveMappings(i,iMapCount); + i--; // Re-attempt to mount the same drive now that the mappings are swapped + } + } + + return(KErrNone); + } +#endif + +#if defined(_LOCKABLE_MEDIA) +/** +Initialise the local media password store with contents of a file. + +@param aFile The file used to initialize the store. Must already be opened for + read access in EFileStreamText mode. + +@return KErrNone if successful, KErrNoMemory if heap is full, otherwise one of the other system-wide error codes. +*/ +TInt TFSStartup::WriteLocalPwStore(RFile& aFile) +// +// Initialise local media password store with contents of aFile +// + { + + DEBUGPRINT("WriteLocalPwStore"); + + TInt size; + TInt r=aFile.Size(size); + if(r!=KErrNone || size==0) + return(r); + HBufC8* hBuf=HBufC8::New(size); + if(hBuf==NULL) + return(KErrNoMemory); + TPtr8 pBuf=hBuf->Des(); + r=aFile.Read(pBuf); + if(r==KErrNone) + { + TBusLocalDrive TBLD; + TBool TBLDChangedFlag; + + for (TInt i=0; iiRemovable, infoPtr->iCapsRetCode); + if (infoPtr->iRemovable || infoPtr->iCapsRetCode == KErrNotReady) + { + r = TBLD.Connect(iDriveMappingInfo[i].iLocalDriveNumber, TBLDChangedFlag); + if(r==KErrNone) + { + r = TBLD.WritePasswordData(pBuf); + DEBUGPRINT2("WritePasswordData on drive %d returned %d", i, r); + TBLD.Disconnect(); + // ignore error if media not ready (it MAY not be a removable drive) + if (r != KErrNone && infoPtr->iCapsRetCode == KErrNotReady) + r = KErrNone; + } + } + } + } + delete hBuf; + return(r); + } + +/** +Attempt to initilise the local media password store. This allows locked media devices +(e.g. password protected MMC cards) to be accessed without notifier. + +@return KErrNone if successful otherwise one of the other system-wide error codes. +*/ +TInt TFSStartup::InitializeLocalPwStore() + { + // Attempt to initilise the local media password store + // Allows locked device to be accessed without notifier + + DEBUGPRINT("InitializeLocalPwStore"); + + RFile f; + TBuf mediaPWrdFile(KMediaPWrdFile); + mediaPWrdFile[0] = (TUint8) RFs::GetSystemDriveChar(); + TInt r=f.Open(iFs,mediaPWrdFile,EFileShareExclusive | EFileStream | EFileRead); + if (r==KErrNone) + { + r=WriteLocalPwStore(f); + __ASSERT_DEBUG(r == KErrNone || r == KErrCorrupt || r == KErrNotReady, Panic(ELitInitLocalPwStoreFail,r)); + f.Close(); + } + return(r); + } +#endif + +#ifdef LOAD_PATCH_LDD +/** +Find any patch LDDs and load them. + +@panic ESTART_8 0; if creation of trap handler failed. +@panic ESTART_9 Error_Code; if loading of LDD failed. + Error_Code is the error code returned by User::LoadLogicalDevice(). +*/ +void TFSStartup::LoadPatchLDDs() + { +#if defined(__EPOC32__) + // Load an LDD to patch any bugs in the ROM + // This will always return an error - ignore it + _LIT(KLitPatchBootLdd,"Z:\\Sys\\Bin\\BOOT.LDD"); + TInt r; + User::LoadLogicalDevice(KLitPatchBootLdd); + + // Install a trap handler - fs.GetDir calls functions which might leave + CTrapCleanup* trapHandler=CTrapCleanup::New(); + __ASSERT_ALWAYS(trapHandler!=NULL,Panic(ELitCreateTrapHandlerFail,0)); + + // Find any patch ldds and load them - files with the .SYS extension and second uid KLogicalDeviceDriverUid + // and third uid KPatchLddUid (0x100000CC, BOOT.LDD should probably be checked for this too) + CDir* patchList=NULL; + _LIT(KLitPatchSysLdd,"?:\\Sys\\Bin\\*.SYS"); + TBuf litPatchSysLdd(KLitPatchSysLdd); + litPatchSysLdd[0] = (TUint8) RFs::GetSystemDriveChar(); + if (iFs.GetDir(litPatchSysLdd,(KEntryAttSystem|KEntryAttAllowUid),ESortByName,patchList)==KErrNone) + { + patchList->Sort(ESortByName); + TInt i; + for (i=0;iCount();i++) + { + TEntry& entry=(*patchList)[i]; + if (entry[1]==KLogicalDeviceDriverUid && entry[2].iUid==KPatchLddUidValue) + { + r=User::LoadLogicalDevice(entry.iName); + __ASSERT_DEBUG(r==KErrNone,Panic(ELitLoadSysLddsFail,r)); + } + } + } + delete trapHandler; +#endif + } +#endif + +/** +Try to add both the ROFS and Composite file systems. + +@return KErrNone if successful, KErrNotFound if either fail to be added. +*/ +TInt TFSStartup::InitCompositeFileSystem() + { + DEBUGPRINT("InitCompositeFileSystem"); + TInt r=iFs.AddFileSystem(KRofs); + if (r==KErrNone || r==KErrAlreadyExists) + { + DEBUGPRINT("ROFS is present"); + r=iFs.AddFileSystem(KCompfs); + if (r==KErrNone || r==KErrAlreadyExists) + { + gMountComposite=ETrue; + gMountRofsAlone=EFalse; + DEBUGPRINT("Comp FS is present"); + return(KErrNone); + } + } + else + gMountRofsAlone=EFalse; + + return(KErrNotFound); + } + +/** +Mount the composite file system on the specified drive. + +@param The number of the drive on which the composite FSY is to be loaded on. + +@panic ESTART_16 Error_Code; If unable to get file system name on the drive. + Error_Code is the error code returned by RFs::FileSystemName(). +@panic ESTART_15 Error_Code; If unable to mount composite file system. + Error_Code is the error code returned by RFs::SwapFileSystem(). +*/ +_LIT(KCompositeName,"Composite"); +void TFSStartup::LoadCompositeFileSystem(TInt aDrive) + { + + if (gMountComposite) + { + DEBUGPRINT1("LoadCompositeFileSystem on %c:",(aDrive+'A')); + TBuf<16> buf; + TInt r=iFs.FileSystemName(buf,aDrive); + DEBUGPRINT1("Read current FSY returns %d",r); + __ASSERT_ALWAYS(r==KErrNone, Panic(EFsNameFail,r)); + __ASSERT_ALWAYS(buf!=KCompositeName, Panic(EFsNameFail,r)); + + DEBUGPRINT1("Swap composite for %S",&buf); + r=iFs.SwapFileSystem(buf,_L("Composite"),aDrive); + DEBUGPRINT1("Swap file system returned %d", r); + __ASSERT_ALWAYS(r==KErrNone, Panic(ECompMountFsFail,r)); + gCompositeMountState=ESwapped; + } + } +/** +Adds a local drive to the composite filesystem. + +@param anInfo A stucture holding mounting flags, drive number info. + +@panic ESTART_15 -11; If composite mount file already exist. +*/ +void TFSStartup::LoadCompositeFileSystem(SLocalDriveMappingInfo& anInfo) + { + + if (gMountComposite) + { + __ASSERT_ALWAYS(gCompositeMountState<2, Panic(ECompMountFsFail,KErrAlreadyExists)); + + TPtrC fsyname; + TBool sync = (anInfo.iFsInfo.iFlags & FS_SYNC_DRIVE)!=0; + + fsyname.Set(anInfo.iFsInfo.iFsyName); + TInt r=iFs.AddFileSystem(fsyname); + DEBUGPRINT2("AddFileSystem(%S) -> %d",&fsyname,r); + __ASSERT_ALWAYS(r==KErrNone || r==KErrAlreadyExists, Panic(ECompMountFsFail,r)); + + TPtrC objname; + objname.Set((anInfo.iFsInfo.iObjName) ? anInfo.iFsInfo.iObjName : anInfo.iFsInfo.iFsyName); + DEBUGPRINT4("LoadCompositeFileSystem on %c: with drive %i (%S) included. Sync=%d",(anInfo.iDriveNumber+'A'),anInfo.iLocalDriveNumber,&objname, anInfo.iFsInfo.iFlags); + r=iFs.AddCompositeMount(objname,anInfo.iLocalDriveNumber,anInfo.iDriveNumber, sync); + DEBUGPRINT1("AddCompositeMount returned %d", r); + if (r==KErrNone) + gCompositeMountState=EHasMounts; + } + } + + +/** +Initialize the local drives.It loads the relevant File Systems (FSYs), +File Server extensions (FXTs) and mounts these on the appropriate drives. +This involves mapping local drives to particular drive letters. +First it attempts to open the local drive mapping file ESTART.TXT.If this file is +found then ESTART loads this and attempts to apply the mapping contained within it. +If a mapping file is not found then it attempts to automatically detect the most +appropriate configuration for each local drive registered. +Hence, if it has been necessary to customize ESTART solely to provide a custom set +of local drive mappings then the generic ESTART can now be used - in conjunction +with a platform specific version of the local drive mapping file: ESTART.TXT. +However The entire local drive initialisation sequence provided by the generic version +of ESTART can be overridden (while possibly re-using some of the services provided by +the generic version). + +@return KErrNone if successful. + +@panic ESTART_11 Error_Code; If drive mapping file was not found and autodetect was not enabled. + Error_Code is the error code returned by ProcessLocalDriveMappingFile(). +*/ +TInt TFSStartup::LocalDriveInit() + { + + TInt i; + for(i=0;i>= 1; + } + iUnmountedDriveBitmask=iRegisteredDriveBitmask; + + TMachineStartupType reason; + UserHal::StartupReason(reason); + if (reason==EStartupCold || reason==EStartupColdReset) + iColdStart=ETrue; + } + +/** +Mount all removable drives. + +@return KErrNone if successful. +*/ +TInt TFSStartup::MountRemovableDrives() + { + DEBUGPRINT("TFSStartup::MountRemovableDrives"); + + for (TInt i=0;iiRemovable) + continue; + TInt r = MountFileSystem(iDriveMappingInfo[i]); + DEBUGPRINT2("Mount drive (%c) -> %d",'A'+iDriveMappingInfo[i].iDriveNumber,r); + if (r==KErrDisMounted) + { + // We have encountered a corrupt internal drive which should be swapped with another internal drive + SwapDriveMappings(i,iMapCount); + i--; // Re-attempt to mount the same drive now that the mappings are swapped + } + } + return KErrNone; + } + +/** +This is the main execution function which is responsible to start the File system. +It sets the default Locale properties. Initializes all the local drives, HAL and +creates the domain manager process. It also loads the locale and mounts all the +removable drives. + +@return KErrNone if successful. + +@panic ESTART_6 Error_Code; If initialization of local properties to default fails. + Error_Code is the error code returned by UserSvr::LocalePropertiesSetDefaults(). +@panic ESTART_1 -1; If unable to create domain manager. +@panic ESTART_2 Error_Code; If initialization of domain manager fails. + Error_Code is the error code returned by RDmDomainManager::WaitForInitialization(). +*/ +TInt TFSStartup::Run() + { + + TInt r = UserSvr::LocalePropertiesSetDefaults(); + __ASSERT_ALWAYS(r==KErrNone,Panic(ELitLocaleInitialisationFail,r)); + + LocalDriveInit(); + +#ifdef AUTO_PROFILE + StartProfiler(); +#endif + InitialiseHAL(); + + + r=LoadCodePageDll(); + if(r != KErrNone) + { + DEBUGPRINT1("\nLoadCodePageDll() FAILED !!! : returned : %d", r); + } + + // Seperate ScanDrive from MountDrive; this allows drives to be mounted + // followed by locale loading. Scanning drives after locale is set thus can + // recognise non-english filename. + MountRemovableDrives(); + +#ifdef _DEBUG + // display the setting for all drives + DEBUGPRINT(" L FSY OBJ EXT Flags FileCacheFlags"); + for(TInt i=0;i codepageDllName; + TBool CodepageFound = EFalse; + +/* Default LanguageID --> LocaleDll --> CodepageDll Mapping. Must be maintained. + |---------------|---------------------------|-------------------------|---------------------------| + | Language ID | Language Name | Locale dll (eloc.xxx) | FATCharsetConv (cpnnn.dll)| + |---------------|---------------------------|-------------------------|---------------------------| + | 29 | TaiwanChinese | elocl.29 | cp950.dll | + | 30 | HongKongChinese | elocl.30 | cp950.dll | + | 31 | PrcChinese | elocl.31 | cp936.dll | + | 32 | Japanese | elocl.32 | cp932.dll | + | 157 | English taiwan | elocl.157 | cp950.dll | + | 158 | English HK | elocl.158 | cp950.dll | + | 159 | English prc | elocl.159 | cp936.dll | + | 160 | English japan | elocl.160 | cp932.dll | + | 326 | Bahas Malay | elocl.326 | cp936.dll | + | 327 | Indonesian(APAC)(Bahasa)| elocl.327 | cp936.dll | + |---------------|---------------------------|-------------------------|---------------------------| + + Language ID is read from the HAL data file as Language Index. Based on the read Language Index, + corresponding Codepage Dll name is created. +*/ + + TInt languageIndex; + TInt error=HAL::Get(HALData::ELanguageIndex,languageIndex); + if (error==KErrNone) + { + switch(languageIndex) + { + case 29: + { + fatConvNumber = 950; + CodepageFound=ETrue; + break; + } + case 30: + { + fatConvNumber = 950; + CodepageFound=ETrue; + break; + } + case 31: + { + fatConvNumber = 936; + CodepageFound=ETrue; + break; + } + case 32: + { + fatConvNumber = 936; + CodepageFound=ETrue; + break; + } + case 157: + { + fatConvNumber = 950; + CodepageFound=ETrue; + break; + } + case 158: + { + fatConvNumber = 950; + CodepageFound=ETrue; + break; + } + case 159: + { + fatConvNumber = 936; + CodepageFound=ETrue; + break; + } + case 160: + { + fatConvNumber = 932; + CodepageFound=ETrue; + break; + } + case 326: + { + fatConvNumber = 936; + CodepageFound=ETrue; + break; + } + case 327: + { + fatConvNumber = 936; + CodepageFound=ETrue; + break; + } + default: + { + CodepageFound=EFalse; + break; + } + } + } + + // Do not use any codepage dll if the language index uses default FATCharsetconv conversions. + if(!CodepageFound) + return KErrNotFound; + + // Create the codepage dll name to be loaded. + switch(fatConvType) + { + // coverity[dead_error_condition] + // Always MS codepage type. Currently only supports the Microsoft Standard codepage names. + case EFatConversionDefault: + // Undefined conversion scheme; conversion obtained is whatever the + // default policy is for this version of the OS. + DEBUGPRINT("...EFatConversionDefault"); + break; + case EFatConversionNonStandard: + // x-fat.dll is loaded, where is the FAT filename conversion number. + DEBUGPRINT("...EFatConversionNonStandard"); + codepageDllName.Format(KNonStandardCodePageName, fatConvNumber); + break; + case EFatConversionMicrosoftCodePage: + // cp.dll is loaded, where is the FAT filename conversion number. + DEBUGPRINT("...EFatConversionMicrosoftCodePage"); + codepageDllName.Format(KMicrosoftStandardCodePageName, fatConvNumber); + break; + default: + DEBUGPRINT("...FAT Conversion Type Unknown"); + break; + } + + // Load the codepage dll. + if(codepageDllName.Length()) + { + // No need for an F32 API to do this - ESTART is then only intended client for now. + // - Note that we load the code page via the loader, as doing so in the file server + // will cause deadlock (as RLibrary::Load depends on the file server). + RLoader loader; + err = loader.Connect(); + if (err==KErrNone) + { + err = loader.SendReceive(ELoadCodePage, TIpcArgs(0, &codepageDllName, 0)); + loader.Close(); + } + DEBUGPRINT2("...Loaded codepage DLL : %S [err: %d]", &codepageDllName, err); + } + + return(err); + } +