os/kernelhwsrv/userlibandfileserver/fileserver/estart/estart.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\estart\estart.cpp
    15 // Generic startup code run by the fileserver on boot
    16 // 
    17 //
    18 
    19 #include <e32std.h>
    20 #include <e32std_private.h>
    21 #include <e32def_private.h>
    22 #include <hal.h>
    23 #include <f32file.h>
    24 #include <f32file_private.h>
    25 #include <f32fsys.h>
    26 #ifndef SYMBIAN_EXCLUDE_ESTART_DOMAIN_MANAGER
    27 #include <domainmanager.h>
    28 #endif
    29 #include <e32uid.h>
    30 #include <e32property.h>
    31 
    32 //#ifndef _DEBUG
    33 //	#define _DEBUG
    34 //#endif
    35 //#define TRACING_ON
    36 
    37 #include "estart.h"
    38 #include <u32exec.h>
    39 
    40 //-- define this macro in order to have system start time measurement (SYSSTATEMGR.EXE process life time)
    41 //#define SYMBIAN_ESTART_OUTPUT_BOOT_TIME
    42 
    43 
    44 TInt LoadCodePageDll();
    45 /** Maximum Codepage Dll name length. */
    46 const TInt KMaxCodepageDllName=16;
    47 
    48 
    49 #ifdef _DEBUG
    50 TBool DebugTraceEnabled()
    51 	{
    52 #ifdef TRACING_ON
    53 	return ETrue;
    54 #else
    55 	return UserSvr::DebugMask() & 2;
    56 #endif
    57 	}
    58 #endif
    59 
    60 _LIT(KEStartPanicCatagory, "ESTART");
    61 
    62 enum TEStartPanic
    63     {
    64     ELitNoDM = 1,                           // No Domain Manager
    65     ELitDMInitFail,                         // Domain Manager init fail
    66     ELitHALFail,                            // HAL init fail
    67     ELitConnectFsFail1,                     // Connect fs 1 fail
    68     ELitInitLocalPwStoreFail,               // Init PwStore fail
    69     ELitLocaleInitialisationFail,           // Initialisation of locale properties failed
    70     ELitFSInitDriveInfoFail,                // FS Init DriveInfo fail
    71     ELitCreateTrapHandlerFail,              // Create trap handler fail
    72     ELitLoadSysLddsFail,                    // Load sys ldds fail
    73     ELitLocalDriveMappingFail,              // Local drive mapping fail
    74     ELitDriveMappingFileFail,               // Drive mapping file not found
    75     ELitSwapMappingFailArrayInconsistent,   // Swap mappings fail - array inconsistent
    76     ELitFsSwapMappingFail,                  // Swap mappings fail - Fs request failed
    77     EPropertyError,                         // RProperty return error
    78     ECompMountFsFail,                       // Failed comp fs mount
    79     EFsNameFail,                            // File system name on Z: failed
    80     ELitNoWS,                               // No WSERV
    81     EStartupModeFail,                       // Get startup mode failed
    82     ESysAgentFail,                          // Fail to launch system agent
    83     ESetSystemDriveFail                     // Fail to set System Drive
    84     };
    85 
    86 inline void Panic(TEStartPanic aPanic, TInt aReason)
    87     {
    88     TBuf<10> panic(KEStartPanicCatagory);
    89     panic.AppendFormat(_L("_%d"), aPanic);
    90     User::Panic(panic, aReason);
    91     }
    92 
    93 _LIT(KRofs,"erofs.fsy");
    94 _LIT(KCompfs,"ecomp.fsy");
    95 _LIT(KEcomp,"ECOMP");
    96 _LIT(KServerPathSysBin, "0:\\Sys\\Bin\\");
    97 _LIT(KSystemAgentName, "z:\\sys\\bin\\SysAgt2Svr.exe");
    98 _LIT(KLitLocaleData,"?:\\System\\Data\\LOCALE.D");
    99 _LIT(KLocaleDllNameBase, "ELOCL");
   100 _LIT(KLocalDriveMappingFile,"Z:\\SYS\\DATA\\ESTART.TXT");
   101 _LIT(KWindowServerRootName1,"EWSRV.EXE");
   102 _LIT(KSystemStarterName, "z:\\sys\\bin\\SYSSTART.EXE");
   103 _LIT(KSystemStateManager, "z:\\sys\\bin\\SYSSTATEMGR.EXE");
   104 
   105 //const TInt KPatchLddUidValue=0x100000cc;	// patch ldds should specify this as their third uid
   106 
   107 GLDEF_D TBool gMountRofsAlone=ETrue;
   108 GLDEF_D TBool gMountComposite=EFalse;
   109 
   110 enum TCompositeMountSate
   111 	{
   112 	ENoMounts,
   113 	EHasMounts,
   114 	ESwapped
   115 	};
   116 	
   117 LOCAL_D TCompositeMountSate gCompositeMountState=ENoMounts;
   118 
   119 #if !defined(AUTODETECT_DISABLE)
   120 LOCAL_D TInt gNCompositeMounts=0;
   121 #endif
   122 
   123 #if defined(__EPOC32__) && defined(__X86__)
   124 LOCAL_D TInt gNFloppies=0;
   125 #endif		
   126 
   127 /**
   128 ASCII text file reader constructor
   129 */
   130 TText8FileReader::TText8FileReader()
   131 	{
   132 	
   133 	iBufPos=-1;
   134 	iFileDataBuf=NULL;
   135 	iFileSize=0;	
   136 	}
   137 
   138 /**
   139 ASCII text file reader desctructor
   140 */
   141 TText8FileReader::~TText8FileReader()
   142 	{
   143 	
   144 	delete[] iFileDataBuf;
   145 	}	
   146 
   147 /**	
   148 Supply an ASCII text file for the file reader. 
   149 This function reads the entire contents of this file into a buffer, converting to
   150 unicode / folding each character. Subsequent parsing of the file data is all done from this
   151 buffer.
   152 @param aFile The file to be read. Must already be opened for read access in EFileStreamText mode.  
   153 @return	KErrNone if no error.
   154 */
   155 TInt TText8FileReader::Set(RFile& aFile)
   156 	{
   157 	
   158 	iFile=aFile;
   159 	iBuf.Zero();
   160 	iBufPos=0;
   161 	
   162 	// Read the size of the file
   163 	TInt r=iFile.Size(iFileSize);
   164 	if (r!=KErrNone || !iFileSize)
   165 		return(KErrGeneral);
   166 	
   167 	// Allocate a buffer to read in the file
   168 	iFileDataBuf=new TText[iFileSize+1];	// +1 in case need to NULL terminate the end of the last string
   169 	if (iFileDataBuf==NULL)
   170 		return(KErrNoMemory);
   171 
   172 	// Read the entire contents of the file into the buffer
   173 	TPtr fdata(NULL,0);	
   174 	TInt pos=0;
   175 	r=iFile.Seek(ESeekStart,pos);
   176 	while (pos<iFileSize)
   177 		{
   178 		if ((r=iFile.Read(iBuf))!=KErrNone)
   179 			return(r);
   180 		fdata.Set((iFileDataBuf+pos),0,iBuf.Length());	
   181 		fdata.Copy(iBuf);
   182 		fdata.Fold();
   183 		pos+=iBuf.Length();	
   184 		}
   185 	return(KErrNone);	
   186 	}
   187 	
   188 /**
   189 Return the next record from the text file.
   190 @param aPtr A TPtr which is setup with the address and length of the next record, referencing
   191 the data in the reader's buffer.
   192 @return	KErrNone if a record is successfully loaded into the buffer, KErrEof if the end of the
   193 file is encountered, KErrGeneral if a file hasn't been set.
   194 */
   195 TInt TText8FileReader::Read(TPtr& aPtr)
   196 	{
   197 	
   198 	// Check that Set() has been called.
   199 	if (iBufPos<0)
   200 		return(KErrGeneral);
   201 		
   202 	// Check if we have run into the end of the file	
   203 	TInt bufRemainder=(iFileSize-iBufPos);
   204 	if (!bufRemainder)
   205 		return(KErrEof);
   206 		
   207 	// Setup the descriptor passed with the next record - don't include the record terminator
   208 	// The line terminators are CR + LF for DOS
   209 	// whereas only LF for Unix line endings
   210 	aPtr.Set((iFileDataBuf+iBufPos),bufRemainder,bufRemainder);
   211 	TInt len=aPtr.Locate('\n');
   212 	if (len != KErrNotFound)
   213 		{
   214 		iBufPos += len;
   215 		// Check for DOS line ending to support both DOS and Unix formats
   216 		if ((len != 0) && (iFileDataBuf[iBufPos-1] == '\r'))
   217 			{
   218 			len--;
   219 			}
   220 		aPtr.SetLength(len);
   221 		}
   222 	else
   223 		iBufPos=iFileSize;
   224 	
   225 	// Point iBufPos to the next non-empty line
   226 	while (iBufPos<iFileSize && (iFileDataBuf[iBufPos]=='\n' || iFileDataBuf[iBufPos]=='\r'))
   227 		iBufPos++;
   228 	return(KErrNone);
   229 	}
   230 
   231 const TInt DefaultLocalDrives[KMaxLocalDrives]=
   232 			{
   233 			EDriveC,               	//0
   234 			EDriveD,                //1
   235 			EDriveE,                //2
   236 			EDriveF,                //3
   237 			EDriveG,                //4
   238 			EDriveH,                //5
   239 			EDriveI,                //6
   240 			EDriveJ,                //7
   241 			EDriveK,				//8
   242 			EDriveL,				//9
   243 			EDriveM,				//10
   244 			EDriveN,				//11
   245 			EDriveO,				//12
   246 			EDriveP,				//13
   247 			EDriveQ,				//14
   248 			EDriveR					//15 
   249 			};
   250 /**
   251 Return the default drive letter for the specified local drive.
   252 To alter the default mapping scheme on auto-configuration, override this function.
   253 
   254 @param aLocalDrive The number of the local drive (0-15).
   255 
   256 @return	The default drive number associated with this local drive.
   257 */			
   258 TInt TFSStartup::DefaultLocalDrive(TInt aLocalDrive)
   259 	{
   260 	
   261 	return(DefaultLocalDrives[aLocalDrive]);
   262 	}
   263 	
   264 //typedef TInt TLocalDriveList[KMaxLocalDrives];
   265 /**
   266 Write the local drive mapping data to the file server. If there is no potential of a drive swap then also commit it.
   267 Once committed, the setting cannot be changed.
   268 
   269 @panic ESTART_10 Error_Code; If unable to set local drive mapping in the file server.
   270 				 Error_Code is the error code returned by RFs::SetLocalDriveMapping()	
   271 
   272 */
   273 void TFSStartup::SetFServLocalDriveMapping()
   274 	{
   275 	
   276 	DEBUGPRINT("SetFServLocalDriveMapping");
   277 	TLocalDriveMappingInfoBuf mBuf;
   278 	TLocalDriveMappingInfo& ldmi=mBuf();
   279 	Mem::Copy(&ldmi.iDriveMapping[0],&iLocalDriveList[0],(KMaxLocalDrives*sizeof(TInt)));
   280 	
   281 	// Can't set the mapping yet - if there is the potential of a drive swap .
   282 	ldmi.iOperation = (iDriveSwapCount) ? TLocalDriveMappingInfo::EWriteMappingsNoSet : TLocalDriveMappingInfo::EWriteMappingsAndSet;
   283 	
   284 	TInt r=iFs.SetLocalDriveMapping(mBuf);
   285     __ASSERT_ALWAYS(r==KErrNone,Panic(ELitLocalDriveMappingFail, r));
   286 	}
   287 
   288 /**
   289 Swap and commit the file server's local drive mapping data. Change the local drive mapping info already set with the file server.
   290 
   291 @param  aFirstDrive		First Drive number to be swapped.
   292 @param  aSecondDrive	Second Drive number to be swapped.
   293 
   294 @panic  ESTART_13 Error_Code; if unable to set the local drive mapping to file server.
   295 				  Error_Code is the error code returned by RFs::SetLocalDriveMapping()	
   296 */
   297 void TFSStartup::SwapFServLocalDriveMapping(TInt aFirstDrive,TInt aSecondDrive)
   298 	{
   299 	
   300 	DEBUGPRINT("SwapFServLocalDriveMapping");
   301 	TLocalDriveMappingInfoBuf mBuf;
   302 	TLocalDriveMappingInfo& ldmi=mBuf();
   303 	ldmi.iDriveMapping[0]=aFirstDrive;
   304 	ldmi.iDriveMapping[1]=aSecondDrive;
   305 	ldmi.iOperation=TLocalDriveMappingInfo::ESwapIntMappingAndSet;
   306 	TInt r=iFs.SetLocalDriveMapping(mBuf);
   307 	__ASSERT_ALWAYS(r==KErrNone,Panic(ELitFsSwapMappingFail,r));
   308 	}
   309 	
   310 
   311 
   312 // Warning - File format changes must be replicated in EikSrv.
   313 struct TLocData
   314 	{
   315 	TLocale iLocale;
   316 	TCurrencySymbol iCurrency;
   317 	};
   318 
   319 /**
   320 Attempt to open the locale data file from system drive. If found, read the 
   321 locale and currency symbol data from this file and transfer it to 'the system'.
   322 
   323 @return KErrNone if successful.
   324 */
   325 TInt TFSStartup::LoadLocale()
   326 	{
   327 	// Append the language index to the standard locale filename.
   328 	TFileName filename(KLitLocaleData);
   329 	filename[0] = (TUint8) RFs::GetSystemDriveChar();
   330 	TInt lang;
   331 	if (HAL::Get(HAL::ELanguageIndex,lang) == KErrNone)
   332 		{
   333 		filename.AppendNumFixedWidth(lang,EDecimal,2);
   334 		HAL::Set(HAL::ELocaleLoaded, lang);
   335 		}
   336 
   337 	// Attempt to open the file, read/set the data. 
   338 	RFile file;
   339 	if (file.Open(iFs,filename,EFileRead) == KErrNone)
   340 		{
   341 		TPckgBuf<TLocData> data;
   342 		if( file.Read(data) == KErrNone && data.Size()==sizeof(TLocData))
   343 			{
   344 			data().iLocale.Set();
   345 			TInt offset = data().iLocale.UniversalTimeOffset().Int();
   346 			if (data().iLocale.QueryHomeHasDaylightSavingOn())
   347 				offset += 3600;
   348 			User::SetUTCOffset(offset);
   349 			User::SetCurrencySymbol(data().iCurrency);
   350 			}
   351 		file.Close();
   352 		}
   353 	return(KErrNone);	
   354 	}
   355 
   356 
   357 /**
   358 Load the Locale DLL
   359 @return KErrNone if successful.
   360 	    KErrNotFound if locale DLL not found.
   361 		Or other system wide error code.
   362 */
   363 TInt LoadLocaleDll()
   364     {
   365     TBuf<16> localeDllName;
   366 
   367     TInt languageIndex;
   368     TInt error=HAL::Get(HALData::ELanguageIndex,languageIndex);
   369     if (error!=KErrNone)
   370         error = KErrNotFound;
   371     else
   372         {
   373         TBuf<6> extension; // Dot plus five digit locale
   374         _LIT(KExtension,".%u");
   375         extension.Format(KExtension, languageIndex);
   376         if (extension.Length()<3) // Padd ".1" to ".01" for compatibility.
   377             {
   378             _LIT(KPadding,"0");
   379             extension.Insert(1,KPadding);
   380             }
   381         localeDllName=KLocaleDllNameBase;
   382         localeDllName.Append(extension);
   383 		error = UserSvr::ChangeLocale(localeDllName);
   384         }
   385     if (error==KErrNotFound)
   386         {
   387 		// Try default locale
   388         _LIT(KLocaleDllNameExtension, ".LOC");
   389         localeDllName=KLocaleDllNameBase;
   390         localeDllName.Append(KLocaleDllNameExtension);
   391 		error = UserSvr::ChangeLocale(localeDllName);
   392         }
   393     if (error == KErrNone)
   394         TLocale().Set();
   395 	return error;
   396     }
   397 
   398 /**
   399 Initialise the HAL.
   400 Search for a saved HAL file - containing a series of saved HAL attributes. 
   401 If found, initialise each attribute saved.
   402 
   403 @return KErrNone if successful; KErrGeneral if the exe panicked.
   404 */
   405 TInt TFSStartup::InitialiseHAL()
   406 	{
   407 	RProcess process;
   408 	TInt result = process.Create(_L("HALSettings.exe"), _L("INITIALISE"));
   409 	if(result != KErrNone)
   410 		return result;
   411 	TRequestStatus status;
   412 	process.Logon(status);
   413 	if (status != KRequestPending)
   414 		process.Kill(0);	// abort 
   415 	else
   416 		process.Resume();	// logon OK
   417 	User::WaitForRequest(status);
   418 
   419 	// Special case to ensure the nonsecure clock offset set function gets called
   420 	TInt nsc_offset = 0;
   421 	result = HAL::Get(HAL::ETimeNonSecureOffset,nsc_offset);
   422 	if (result == KErrNone) 
   423 		{
   424 		HAL::Set(HAL::ETimeNonSecureOffset,nsc_offset); // this will only succeed when hal.dat is missing and the function wasnt called by halsettings.exe
   425 		}
   426 
   427 	
   428 	// we can't use the 'exit reason' if the exe panicked as this
   429 	// is the panic 'reason' and may be '0' which cannot be distinguished
   430 	// from KErrNone
   431 	result = process.ExitType() == EExitPanic ? KErrGeneral : status.Int();
   432 	process.Close();
   433 	return result;
   434 	}
   435 
   436 /**
   437 Create and resume a server. Start without specifying a path. 
   438 If this fails, then systematically try to start it from 
   439 each valid drive in turn (Y: - A:, then Z:). 
   440 The second phase is to handle the sitation where a version 
   441 of the executable is found on a drive early in the search order
   442 (e.g. C:) - that fails to load. Rather than failing the load 
   443 on the 1st error, this function keeps going through all the valid drives.
   444 
   445 @param aDrives		The drive list, to determine which are valid.
   446 @param aRootName	The root name of the executable.
   447 
   448 @return	ETrue if the server was eventually created successfully, EFalse if not.
   449 */
   450 TBool TFSStartup::CreateServer(const TDriveList& aDrives, const TDesC& aRootName)
   451 	{
   452 	RProcess ws;
   453 	TInt r=ws.Create(aRootName, KNullDesC);
   454 	if (r!=KErrNone)
   455 		{
   456 		TFileName name;
   457 		name = KServerPathSysBin();
   458 		name+=aRootName;
   459 		TInt i=EDriveZ;
   460 		FOREVER
   461 			{
   462 			i= (i==0) ? EDriveZ : i-1;
   463 			if (aDrives[i]!=KDriveAbsent) // Got a valid drive
   464 				{
   465 				name[0]=(TText)('A'+i); // Set the drive letter
   466 				r=ws.Create(name,KNullDesC);
   467 				if (r==KErrNone)
   468 					break;
   469 				}
   470 			if (i==EDriveZ)
   471 				return EFalse;
   472 			}
   473 		}
   474 	ws.Resume();
   475 	ws.Close();
   476 	return ETrue;
   477 	}
   478 
   479 #ifdef AUTO_PROFILE
   480 _LIT(KProfilerName,"profiler.exe");
   481 _LIT(KProfilerCmd,"start");
   482 /**
   483 Start the profiler
   484 */
   485 void TFSStartup::StartProfiler()
   486 	{
   487 	RProcess p;
   488 	TInt r=p.Create(KProfilerName,KProfilerCmd);
   489 	if (r==KErrNone)
   490 		{
   491 		p.Resume();
   492 		p.Close();
   493 		}
   494 	}
   495 #endif
   496 
   497 #if !defined(AUTODETECT_DISABLE)
   498 /**
   499 FSY detection function for the local FSY (assumed to be FAT). This will return success for MMC,
   500 ATA, Floppy and IRAM devices that are FAT formatted. Will also return success for any drive
   501 (other than those designated for CD ROMs) which isn't ready - assuming these to be removable FAT
   502 formatted devices. For floppy devices detected on the X86 build, we need to change the drive
   503 mapping so that these are mounted on drives A: or B:.
   504 */
   505 GLDEF_C TInt DetectELocal(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   506 	{
   507 	(void)ld;
   508 	(void)cr;
   509 	TInt socknum;
   510 	if (cr==KErrNotReady && caps.iType != EMediaCdRom)
   511 		{
   512 #if defined(__EPOC32__) && defined(__X86__)
   513 		// For FDD iEraseBlockSize top 16 bits is sectors per track
   514 		if (caps.iType==EMediaFloppy && (caps.iEraseBlockSize>>16))
   515 			{
   516 pc_floppy:
   517 			if (gNFloppies < 2)
   518 				{
   519 				// Change the default mapping to A: or B:
   520 				TInt ret = gNFloppies ? EDriveB : EDriveA;
   521 				++gNFloppies;
   522 				return KFsDetectMappingChangeReturnOffset + ret;
   523 				}
   524 			return KErrNone;
   525 			}
   526 #endif
   527 		return KErrNone;	// Removable and not ready - assume fat
   528 		}
   529 	if(cr == KErrCorrupt && ld.IsRemovable(socknum)) // Removable and media corrupt - assume fat
   530 		{
   531 		return KErrNone;
   532 		}
   533 	if (caps.iType!=EMediaFloppy && caps.iType!=EMediaHardDisk)
   534 		return KErrGeneral;
   535 	if (cr==KErrNone && (PartitionIsFAT32(caps.iPartitionType) || PartitionIsFAT(caps.iPartitionType)) )
   536 		{
   537 #if defined(__EPOC32__) && defined(__X86__)
   538 		if (cr!=KErrNotSupported && caps.iType==EMediaFloppy && (caps.iEraseBlockSize>>16))
   539 			goto pc_floppy;
   540 #endif		
   541 		return KErrNone;
   542 		}
   543 	return KErrGeneral;
   544 	}
   545 	
   546 /**
   547 FSY detection function for the local FSY (assumed to be FAT) running over internal RAM. This will
   548 return success for any drive containing RAM media which reports a FAT16 partition type.
   549 */	
   550 GLDEF_C TInt DetectIRam(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   551 	{
   552 	(void)ld;
   553 	(void)cr;
   554 	if (caps.iType==EMediaRam && caps.iPartitionType==KPartitionTypeFAT16)
   555 		return KErrNone;
   556 	return KErrGeneral;
   557 	}	
   558 	
   559 /**
   560 FSY detection function for the local FSY (assumed to be FAT) running over a NAND FTL. This will
   561 return success for any drive containing NAND media which reports a FAT16 partition type.
   562 */	
   563 GLDEF_C TInt DetectFtl(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   564 	{
   565 	(void)ld;
   566 	(void)cr;
   567 	if (caps.iType==EMediaNANDFlash && caps.iPartitionType==KPartitionTypeFAT16)
   568 		return KErrNone;
   569 	return KErrGeneral;
   570 	}
   571 		
   572 /**
   573 FSY detection function for the ROFS FSY. This will return success for any drive containing NAND
   574 media which reports a ROFS partition type as long as the ROFS FSY is present - but not the Composite FSY   
   575 */
   576 GLDEF_C TInt DetectRofs(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   577 	{
   578 	(void)ld;
   579 	(void)cr;
   580 	if ((caps.iType==EMediaNANDFlash) && caps.iPartitionType==KPartitionTypeRofs && gMountRofsAlone)
   581 		return KErrNone;
   582 	return KErrGeneral;
   583 	}
   584 
   585 /**
   586 FSY detection function for the Composite FSY. This will return success for the 1st drive containing NAND
   587 media which reports a ROFS partition type as long as both the ROFS and Composite FSYs are present. We
   588 change the DRIVE mapping so that this is mounted on drive Z:. Any subsequent ROFS partitions detected
   589 can be mounted as ROFS.
   590 */
   591 GLDEF_C TInt DetectComposite(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   592 	{
   593 	(void)ld;
   594 	(void)cr;
   595 	if ((caps.iType==EMediaNANDFlash) && caps.iPartitionType==KPartitionTypeRofs && gMountComposite)
   596 		{
   597 		if (!gNCompositeMounts)
   598 			{
   599 			gNCompositeMounts++;
   600 			gMountRofsAlone=ETrue;		// Any further ROFS drives found can be mounted as such
   601 			return(KFsDetectMappingChangeReturnOffset+EDriveZ);
   602 			}
   603 		}	
   604 	return KErrGeneral;
   605 	}
   606 	
   607 /**
   608 FSY detection function for the LFFS FSY. This will return success for any drive containing NOR
   609 media which reports an LFFS partition type.   
   610 */
   611 GLDEF_C TInt DetectEneaLFFS(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   612 	{
   613 	(void)ld;
   614 	(void)cr;
   615 	if (caps.iType==EMediaFlash && caps.iPartitionType==KPartitionTypeEneaLFFS)
   616 		return KErrNone;
   617 	return KErrGeneral;
   618 	}
   619 
   620 /**
   621 FSY detection function for the ISO 9660 FSY (X86 only). This will return success for CD ROM
   622 devices.   
   623 */
   624 GLDEF_C TInt DetectIso9660(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   625 	{
   626 	(void)ld;
   627 	(void)cr;
   628 	if (caps.iType == EMediaCdRom)
   629 		return KErrNone;
   630 	return KErrGeneral;
   631 	}
   632 
   633 /**
   634 FSY detection function for the NTFS FSY (X86 only). This will return success for any drive
   635 containing a hard disk device which reports an NTFS partition type.   
   636 */
   637 GLDEF_C TInt DetectNtfs(RLocalDrive ld, TInt cr, TLocalDriveCapsV2& caps)
   638 	{
   639 	(void)ld;
   640 	(void)cr;
   641 	if (caps.iType==EMediaHardDisk && PartitionIsNTFS(caps.iPartitionType))
   642 		return KErrNone;
   643 	return KErrGeneral;
   644 	}
   645 #endif	
   646 
   647 /**
   648 Format a drive.
   649 
   650 @param aDrive The number of the drive to be formatted (0-25).
   651 
   652 @return	KErrNone if no error otherwise one of the other system wide error codes.
   653 */
   654 TInt TFSStartup::FormatDrive(TInt aDrive)
   655 	{
   656 	TBuf<2> driveName(_S("A:"));
   657 	driveName[0] = (TText)(aDrive+'A');
   658 	RFormat format;
   659 	TInt count;
   660 	TInt d = format.Open(iFs, driveName, EHighDensity, count);
   661 	DEBUGPRINT2("FormatOpen %S -> %d", &driveName, d);
   662 	if(d!=KErrNone)
   663 		return d;
   664     ShowFormatProgress(count, aDrive);
   665 #ifdef _DEBUG
   666 	TInt lastCount = -1;
   667 #endif
   668     while (d==KErrNone && count)
   669 		{
   670 #ifdef _DEBUG
   671 		if (lastCount != count)
   672 			DEBUGPRINT1("Format count %d", count);
   673 		lastCount = count;
   674 #endif
   675 		d=format.Next(count);
   676         ShowFormatProgress(count, aDrive);
   677 		}
   678 	format.Close();
   679 	DEBUGPRINT1("Format complete %d", d);
   680 	return d;
   681 	}
   682 
   683 /**
   684 Set System Drive if defined either in ESTART.TXT or in HALData::ESystemDrive
   685 */
   686 void TFSStartup::SetSystemDrive()
   687 	{
   688 	DEBUGPRINT("TFSStartup::SetSystemDrive");
   689 	for(TInt i=0; i<iMapCount; i++)
   690 		{
   691 		if(iDriveMappingInfo[i].iFsInfo.iFlags&FS_SYSTEM_DRIVE)
   692 			{
   693 			TInt err = iFs.SetSystemDrive((TDriveNumber)iDriveMappingInfo[i].iDriveNumber);
   694 			DEBUGPRINT3("SetSystemDrive from FILE [%d], %d, err:%d", i, iDriveMappingInfo[i].iDriveNumber, err);
   695 			__ASSERT_ALWAYS(err==KErrNone, Panic(ESetSystemDriveFail, err));
   696 			}
   697 		}
   698 		
   699 	TInt drive = KErrNotFound;
   700 	TInt err = HAL::Get(HAL::ESystemDrive, drive);
   701 	if(err == KErrNone && drive >= EDriveA && drive <= EDriveZ)
   702 		{
   703 		err = iFs.SetSystemDrive((TDriveNumber)drive);
   704 		DEBUGPRINT2("SetSystemDrive from HAL %d, err:%d", drive, err);
   705 		__ASSERT_ALWAYS(err==KErrNone || err==KErrAlreadyExists, Panic(ESetSystemDriveFail, err));
   706 		}
   707 	}
   708 
   709 
   710 /**
   711 Parse the flags field of a drive mapping record that has been read from the drive mapping file.
   712 The flags field text is expected to contain one or more flags, each delimited with a "," char. 
   713 Override this function to support custom drive configuation flags.
   714 
   715 @param aFlagDesc	Non-modifiable descriptor holding the flags record text to be parsed.
   716 @param aFlagVar		An integer to hold the returned flag settings.
   717 @param aSpare		An integer to hold any additional info returned. 
   718 
   719 @return	Always returns KErrNone (but derived version may not).
   720 */
   721 TInt TFSStartup::ParseMappingFileFlags(const TPtrC& aFlagDesc,TUint32& aFlagVar,TInt& aSpare)
   722 	{
   723 
   724 	TInt r=KErrNone;
   725 	TInt pos=0;
   726 	TInt len;
   727 	TPtrC ptr;
   728 	TBool endOfFlagDesc=EFalse; 
   729 	aFlagVar=0;
   730 	while (!endOfFlagDesc && r==KErrNone) 
   731 		{
   732 		ptr.Set(aFlagDesc.Mid(pos));
   733 		len=ptr.Locate(',');
   734 		if (len==KErrNotFound)
   735 			endOfFlagDesc=ETrue;
   736 		else
   737 			{	
   738 			ptr.Set(ptr.Left(len));
   739 			pos+=(len+1);
   740 			} 
   741 		if (ptr.MatchF(_L("FS_FORMAT_ALWAYS"))!=KErrNotFound)
   742 			aFlagVar|=FS_FORMAT_ALWAYS;
   743 		else if (ptr.MatchF(_L("FS_FORMAT_COLD"))!=KErrNotFound)
   744 			aFlagVar|=FS_FORMAT_COLD;		
   745 		else if (ptr.MatchF(_L("FS_FORMAT_CORRUPT"))!=KErrNotFound)
   746 			aFlagVar|=FS_FORMAT_CORRUPT;		
   747 		else if (ptr.MatchF(_L("FS_DISMNT_CORRUPT"))!=KErrNotFound)
   748 			aFlagVar|=FS_DISMNT_CORRUPT;
   749 		else if (ptr.MatchF(_L("FS_SWAP_CORRUPT*"))!=KErrNotFound)
   750 			{
   751 			len=ptr.Locate('-');
   752 			if (iFs.CharToDrive(ptr[len+1],aSpare)==KErrNone && iDriveSwapCount==0) // We only allow one swap
   753 				{
   754 				aFlagVar|=FS_SWAP_CORRUPT;
   755 				iDriveSwapCount++;
   756 				}
   757 			}
   758 		else if (ptr.MatchF(_L("FS_SYNC_DRIVE"))!=KErrNotFound)
   759 			aFlagVar|=FS_SYNC_DRIVE;
   760 		else if (ptr.MatchF(_L("FS_SCANDRIVE"))!=KErrNotFound)
   761 			aFlagVar|=FS_SCANDRIVE;	
   762 		else if (ptr.MatchF(_L("FS_COMPOSITE"))!=KErrNotFound)
   763 			aFlagVar|=FS_COMPOSITE;
   764 		else if (ptr.MatchF(_L("FS_NO_MOUNT"))!=KErrNotFound)
   765 			aFlagVar|=FS_NO_MOUNT;	
   766 		else if (ptr.MatchF(_L("FS_ALLOW_REM_ACC"))!=KErrNotFound)
   767 			aFlagVar|=FS_ALLOW_REM_ACC;
   768 		else if (ptr.MatchF(_L("FS_NOT_RUGGED")) != KErrNotFound)
   769 			aFlagVar |= FS_NOT_RUGGED;
   770 		else if (ptr.MatchF(_L("FS_SYSTEM_DRIVE")) != KErrNotFound)
   771 			aFlagVar |= FS_SYSTEM_DRIVE;
   772 		else	
   773 			r=ParseCustomMountFlags(&ptr,aFlagVar,aSpare);
   774 		}
   775 	return(r);
   776 	}
   777 
   778 /**
   779 Parse for custom mount flags - default implementation.
   780 In either the auto-configuration scheme or the drive mapping file scheme, 
   781 to add support for additional mount flags, this function needs to be override.
   782 
   783 @param aFlagPtr		The flag text.
   784 @param aFlags		An integer to hold the returned mount flag settings
   785 @param aSpare		An integer to hold any additional info returned.
   786 
   787 @return	KErrNone if no error.
   788 */ 
   789 TInt TFSStartup::ParseCustomMountFlags(TPtrC* /*aFlagPtr*/,TUint32& /*aFlags*/,TInt& /*aSpare*/)
   790 	{
   791 	
   792 	return(KErrNone);
   793 	}
   794 		
   795 /**
   796 Process any custom mount flags - default implementation.
   797 In either the auto-configuration scheme or the drive mapping file scheme, 
   798 to add support for additional mount flags, this function needs to be override.
   799 
   800 @param aMountRet	The value returned when attempting to mount the drive.
   801 @param aFlags		The mount flags.
   802 @param aSpare		An integer containing any additional info associated with the flags.
   803 @param aDrive		The drive number.
   804 
   805 @return	KErrNone if no error.
   806 */
   807 TInt TFSStartup::HandleCustomMountFlags(TInt& /*aMountRet*/,TInt& /*aFlags*/,TInt& /*aSpare*/,TInt /*aDrive*/)
   808 	{
   809 
   810 	return(KErrNone);
   811 	}
   812 
   813 /**
   814 Process the local drive field of a drive mapping record
   815 
   816 @param aDriveDesc The comma seperated local drives
   817 @param aDrives An array of drive numbers (return reference)
   818 @param aCount The number of local drives found.
   819 
   820 @return	KErrNone if no error, otherwise a System-wide error code.
   821 */
   822 TInt TFSStartup::ParseMappingFileLocalDrive(const TPtrC& aDriveDesc,TUint32 (&aDrives)[KMaxLocalDrives],TInt& aCount)
   823 	{
   824 
   825 	TInt len;
   826 	TInt pos=0;
   827 	TPtrC ptr;
   828 	TBool endOfDriveDesc=EFalse; 
   829 	TInt err = KErrNone;
   830 	aCount=0;
   831 	while (!endOfDriveDesc) 
   832 		{
   833 		ptr.Set(aDriveDesc.Mid(pos));
   834 		len=ptr.Locate(',');
   835 		if (len==KErrNotFound)
   836 			endOfDriveDesc=ETrue;
   837 		else
   838 			{	
   839 			ptr.Set(ptr.Left(len));
   840 			pos+=(len+1);
   841 			} 
   842 		// Get numeric value
   843 		TLex lex;
   844 		lex.Assign(ptr);
   845 		lex.SkipSpace();
   846 		TUint32 locDrvNum;
   847 		if (lex.BoundedVal(locDrvNum,EDecimal,(KMaxLocalDrives-1))!=KErrNone)
   848 	        return(KErrArgument);
   849 		// Store
   850 		if(aCount >= KMaxLocalDrives)
   851 			return KErrOverflow;
   852 		aDrives[aCount]=locDrvNum;
   853 		++aCount;
   854 		}
   855 	return err;
   856 	}
   857 
   858 
   859 /**
   860 Parse a drive mapping record that has been read from the drive mapping file.
   861 
   862 @param aTextLine	Modifiable ptr descriptor holding the mapping record text 
   863 					to be parsed. Note that this function will null-terminate 
   864 					any FSY or extension names it detects. This will generally
   865 					result in the over-writing of the field separator or end of 
   866 					record delimitor but consideration is required where a 
   867 					mapping file ends with such a string.
   868 @param anInfo		A stucture to hold the returned mapping settings, 
   869 					FSY/ext name string pointers and mounting flags.
   870 
   871 @return	KErrNone if record is successfully parsed and 'anInfo' contains 
   872 		mapping info to be applied. 
   873 		KErrNotFound if the record is a comment line. 
   874 		KErrArgument if the syntax of record is incorrect.
   875 */
   876 TInt TFSStartup::ParseMappingRecord(TPtr& aTextLine,SLocalDriveMappingInfo& anInfo)
   877 	{
   878 	TPtrC token;
   879 	TLex lex(aTextLine);
   880 	
   881 	TInt driveNumber = KDriveInvalid;
   882 	TUint32 localDriveNums[KMaxLocalDrives];
   883 	const TText* fsyName = NULL;
   884 	const TText* objName = NULL;
   885 	const TText* extName = NULL;
   886 	TUint32 flags = 0;
   887 	TInt spare = 0;
   888 	
   889 	// Get all of the above Attributes.
   890 
   891 	
   892 	token.Set(lex.NextToken());
   893 	if (token.Length() <= 1 || token[0]=='#')				// Blank line or comment line
   894 		return(KErrNotFound);
   895 		
   896 	// Drive number		
   897 	if (token[1]!=':' || iFs.CharToDrive(token[0],driveNumber)!=KErrNone)
   898 		return(KErrArgument);
   899 
   900 	// Local drive number(s)
   901 	lex.SkipSpace();
   902 	token.Set(lex.NextToken());
   903 	TInt localDriveCount = 0;
   904 	TInt err = ParseMappingFileLocalDrive(token,localDriveNums,localDriveCount);
   905 	if(err != KErrNone)
   906 		{
   907 		return err;
   908 		}
   909 	if(localDriveCount==0)
   910 		{
   911 		return KErrArgument;
   912 		}
   913 				
   914 	TInt tokLen;
   915 	TPtr fileName(NULL,0);
   916 	TBool endOfRecord = EFalse;
   917 	
   918 	// .FSY file name
   919 	token.Set(lex.NextToken());
   920 	if (!endOfRecord && (token.Length()==0 || token[0]=='#'))
   921 		endOfRecord = ETrue;
   922 	else
   923 		{
   924 		if (token[0]!='0')
   925 			{
   926 			tokLen=token.Length();
   927 			fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1);
   928 			token.Set(lex.NextToken());
   929 			fsyName=fileName.PtrZ();
   930 			}
   931 		else
   932 			{
   933 			token.Set(lex.NextToken());
   934 			}
   935 		}
   936 		
   937 	// Object name of .FSY
   938 	if (!endOfRecord && (token.Length()==0 || token[0]=='#'))
   939 		{
   940 		endOfRecord = ETrue;
   941 		}
   942 	else // Get FSY
   943 		{
   944 		if (token[0]!='0')
   945 			{
   946 			tokLen=token.Length();
   947 			fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1);
   948 			token.Set(lex.NextToken());
   949 			objName=fileName.PtrZ();
   950 			}
   951 		else
   952 			{
   953 			token.Set(lex.NextToken());
   954 			}
   955 		}
   956 		
   957 	// Extension name
   958 	if (!endOfRecord && (token.Length()==0 || token[0]=='#'))
   959 		{
   960 		endOfRecord = ETrue;
   961 		}
   962 	else // Get extension
   963 		{
   964 		if (token[0]!='0')
   965 			{
   966 			tokLen=token.Length();
   967 			fileName.Set((TUint16*)token.Ptr(),tokLen,tokLen+1);
   968 			token.Set(lex.NextToken());
   969 			extName=fileName.PtrZ();
   970 			}
   971 		else
   972 			{
   973 			token.Set(lex.NextToken());
   974 			}
   975 		}
   976 
   977 	// Flags
   978 	if (!endOfRecord && (token.Length()==0 || token[0]=='#'))
   979 		{
   980 		endOfRecord = ETrue;
   981 		}
   982 	else // Get Flags
   983 		{
   984 		if (token[0]!='0')
   985 			{
   986 			TInt r=ParseMappingFileFlags(token,flags,spare);
   987 			if(r!=KErrNone)
   988 				return r;
   989 			}
   990 		}
   991 
   992 	//
   993 	// For every local drive
   994 	//
   995 	SLocalDriveMappingInfo* mappingInfo = &anInfo;
   996 	for(TInt i = 0; i<localDriveCount; i++)
   997 		{
   998 		if(iMapCount >= KMaxLocalDrives)
   999 			return KErrOverflow;
  1000 		Mem::FillZ(mappingInfo,sizeof(SLocalDriveMappingInfo));
  1001 		
  1002 		mappingInfo->iDriveNumber = driveNumber;
  1003 		mappingInfo->iLocalDriveNumber = localDriveNums[i];
  1004 		mappingInfo->iFsInfo.iExtName = extName;
  1005 		mappingInfo->iFsInfo.iFsyName = fsyName;
  1006 		mappingInfo->iFsInfo.iObjName = objName;
  1007 		mappingInfo->iSpare = spare;
  1008 		mappingInfo->iFsInfo.iFlags = flags;
  1009 		
  1010 		// If there was more than 1 local drive number (multi-slot device)
  1011 		// then increase iMapCount so that the mappingInfo doesn't get
  1012 		// clobbered next time this function is called.
  1013 		if(i>=1 && ((TInt)localDriveNums[i])!=KDriveInvalid)
  1014 			{
  1015 			iMapCount++;
  1016 			DEBUGPRINT2("Alternative Entry found for registered ldrive:%d -> %c:",localDriveNums[i],(mappingInfo->iDriveNumber+'A'));
  1017 			}
  1018 		mappingInfo++;
  1019 		}
  1020 	return KErrNone;	
  1021 	}
  1022 	
  1023 /**
  1024 This is only called if a mapping configuration has specified "FS_SWAP_CORRUPT". 
  1025 If it is necessary to implement the drive swap then it is required that 
  1026 the entry for the second drive involved in the swap (ie the one specified 
  1027 in "FS_SWAP_CORRUPT-<drv>") occurs later in the mapping array than the one 
  1028 specifying the swap. This functions checks whether the ordering is OK and 
  1029 swaps the entries for the two drives if necessary. 
  1030 
  1031 @param aTotalEntries The total number of valid entries in the mapping array. 
  1032 */	
  1033 void TFSStartup::CheckAndReOrderArrayForSwapping(TInt aTotalEntries)
  1034 	{
  1035 	
  1036 	// Find the swapper - and determine its entry number
  1037 	TInt i;
  1038 	for (i=0;i<aTotalEntries;i++)
  1039 		{
  1040 		if (iDriveMappingInfo[i].iFsInfo.iFlags & FS_SWAP_CORRUPT)
  1041 			break;
  1042 		}	
  1043 	if (i==aTotalEntries)
  1044 		return;
  1045 	TInt swapperEntryNo=i;
  1046 	TInt swappeeDrvNo=iDriveMappingInfo[i].iSpare;
  1047 	
  1048 	// Now find the swappee and determine its entry number 
  1049 	for (i=0;i<aTotalEntries;i++)
  1050 		{
  1051 		if (iDriveMappingInfo[i].iDriveNumber == swappeeDrvNo)
  1052 			break;
  1053 		}
  1054 	if (i==aTotalEntries)
  1055 		return;	
  1056 	TInt swappeeEntryNo=i;
  1057 	
  1058 	// If swappee comes before swapper then we need to switch then around
  1059 	if (swapperEntryNo>swappeeEntryNo)
  1060 		{
  1061 		SLocalDriveMappingInfo tmp;
  1062 		tmp=iDriveMappingInfo[swapperEntryNo];
  1063 		iDriveMappingInfo[swapperEntryNo]=iDriveMappingInfo[swappeeEntryNo];
  1064 		iDriveMappingInfo[swappeeEntryNo]=tmp;
  1065 		}			
  1066 	}	
  1067 
  1068 /**
  1069 Swap the local drive mappings of two entries in the mapping array. Also, update the local drive mapping previously
  1070 written to the file server.
  1071 
  1072 @param aCurrentEntry	The position in the mapping array of the next mapping to be applied. 
  1073 						This coincides with the drive which has 'requested' the swap. 
  1074 						(The other mapping involved in the swap is guarenteed to be later 
  1075 						in the list and therefore not yet applied).
  1076 @param aTotalEntries	The total number of valid entries in the mapping array. 
  1077 
  1078 @panic  ESTART_12 0; If swap mapping file array is inconsistent.
  1079 */
  1080 void TFSStartup::SwapDriveMappings(TInt aCurrentEntry,TInt aTotalEntries)
  1081 	{
  1082 	DEBUGPRINT1("TFSStartup::SwapDriveMappings - Index %d",aCurrentEntry);
  1083 	TInt firstDrive=iDriveMappingInfo[aCurrentEntry].iDriveNumber;
  1084 	TInt secondDrive=iDriveMappingInfo[aCurrentEntry].iSpare;
  1085 	
  1086 	// Find the entry for the other mapping that we need to swap with
  1087 	TInt secondEntry;
  1088 	for (secondEntry=aCurrentEntry ; secondEntry<aTotalEntries ; secondEntry++)
  1089 		{	
  1090 		if (iDriveMappingInfo[secondEntry].iDriveNumber==secondDrive)
  1091 			break;
  1092 		}
  1093 	if (secondEntry==aTotalEntries)
  1094 		Panic(ELitSwapMappingFailArrayInconsistent,0);
  1095 	
  1096 	// Swap the entries over in the list of mappings still to be applied
  1097 	iDriveMappingInfo[aCurrentEntry].iDriveNumber=secondDrive;
  1098 	iDriveMappingInfo[secondEntry].iDriveNumber=firstDrive;
  1099 	
  1100 	// If second drive is replacing one that is corrupt then we always want to mount it
  1101 	iDriveMappingInfo[secondEntry].iFsInfo.iFlags&=~FS_NO_MOUNT; 	
  1102 	
  1103 	// Change the local drive mapping info already set with the file server
  1104 	SwapFServLocalDriveMapping(firstDrive,secondDrive);
  1105 	iDriveSwapCount=0;		// Swap now handled and the FS local drive mapping is set
  1106 	}
  1107 
  1108 /** 
  1109 Return the filename of the drive mapping file. If it is required to vary 
  1110 the local drive mapping for a given platform, depending on a particular platform 
  1111 specific setting (e.g. state of a switch or jumper setting, detection of 
  1112 a particular h/w feature etc) then it is still possible to use the map file scheme. 
  1113 In this situation, the ROM can be built with more than one mapping file. 
  1114 A custom version of ESTART should then override this virtual function to detect 
  1115 the current setting and return the name of the appropriate map file.
  1116 
  1117 @return	A non-modifiable ptr descriptor containing the path and filename of the mapping file.
  1118 */ 
  1119 TPtrC TFSStartup::LocalDriveMappingFileName()
  1120 	{
  1121 	
  1122 	return(KLocalDriveMappingFile());
  1123 	}
  1124 
  1125 /**
  1126 Open the drive mapping file, and process each mapping record it contains. 
  1127 For each record, this involves updating the local drive list, adding the FSY and 
  1128 any extension specified and then mounting these on the drive in question - 
  1129 processing any mounting flags in the process. The local drive mapping is also 
  1130 written to the File Server.
  1131 
  1132 Calls InitCompositeFileSystem but carries on should this fail. 
  1133 
  1134 @return	KErrNone if no error.
  1135 */
  1136 TInt TFSStartup::ProcessLocalDriveMappingFile()
  1137 	{
  1138 	
  1139 	DEBUGPRINT("ProcessLocalDriveMappingFile");
  1140 	
  1141 	TInt r = InitCompositeFileSystem();
  1142 	__ASSERT_ALWAYS(r==KErrNone || r==KErrNotFound || r==KErrAlreadyExists,User::Panic(_L("EStart init composite fs failed"),r));
  1143 
  1144 	// Following block of code tries to initialise the reading facilities of 
  1145 	//	estart.txt file.
  1146 	// Note: RFs::InitialisePropertiesFile() MUST always be called even there
  1147 	// 	is no estart.txt file. It is for the default construction of File 
  1148 	//	Cache Manager and Global Cache Memory Manager.
  1149 	RFile f;
  1150 	TPtrC mappingFileName(LocalDriveMappingFileName());
  1151 	r=f.Open(iFs,mappingFileName,EFileShareExclusive|EFileStreamText|EFileRead);
  1152 	DEBUGPRINT2("Opening mapping file %S -> %d", &mappingFileName, r);
  1153 	if (r == KErrNone)
  1154 		{
  1155 		// pass ROM address of estart.txt file to file server to allow it to support
  1156 		// reading of ".ini file" - style parameters
  1157 		TInt romAddress = 0;
  1158 		r = f.Seek(ESeekAddress, romAddress);
  1159 		if(r == KErrNone)
  1160 			{
  1161 			TInt size = 0;
  1162 			r = f.Size(size);
  1163 			if (r == KErrNone)
  1164 				{
  1165 				if(size > 0)
  1166 					{
  1167 					TPtrC8 ptr((TUint8*)romAddress, size);
  1168 					iFs.InitialisePropertiesFile(ptr);
  1169 					}
  1170 				else
  1171 					{
  1172 					r = KErrGeneral;
  1173 					}
  1174 				}
  1175 			}
  1176 		}
  1177 	// If any error detected found, the default version of RFs::InitialisePropertiesFile()
  1178 	// 	will be called before exiting.
  1179 	if (r!=KErrNone)
  1180 		{
  1181 		TPtrC8 ptr(0, 0);  
  1182 		iFs.InitialisePropertiesFile(ptr);
  1183 		return(r);
  1184 		}
  1185 
  1186 
  1187 
  1188 	// Create a mapping file reader and pass it the file object. This will also result in the copying of the contents of
  1189 	// the file into reader's buffer. Mapping information read from the file will include pointers to text strings in
  1190 	// this buffer and so the reader object must not be deleted until processing is complete.
  1191 	iMapFile = new TText8FileReader;
  1192 	if (!iMapFile)
  1193 		{
  1194 		f.Close();
  1195 		return(KErrNoMemory);
  1196 		}
  1197 	r=iMapFile->Set(f);
  1198 	DEBUGPRINT1("Reading map file returns %d",r);
  1199 	f.Close();			// Can't leave file on Z: open too long because can't mount composite FSY on Z: in this sitaution
  1200 	if (r!=KErrNone)
  1201 		return(r);
  1202 	
  1203 	// Parse each drive mapping record in turn, saving the information in an array of mapping structures - one for
  1204 	// each valid record.
  1205 
  1206 	TPtr linePtr(NULL,0);
  1207 	iMapCount=0;
  1208 	SLocalDriveMappingInfo* infoPtr;
  1209 	while ((r=iMapFile->Read(linePtr))==KErrNone && iMapCount<KMaxLocalDrives)
  1210 		{		
  1211 		infoPtr=&iDriveMappingInfo[iMapCount];
  1212 		if (ParseMappingRecord(linePtr,*infoPtr)==KErrNone)
  1213 			{
  1214 			// Valid mapping record found
  1215 			TInt localDriveNumber=infoPtr->iLocalDriveNumber;
  1216             __ASSERT_DEBUG(localDriveNumber >=0 && localDriveNumber < KMaxLocalDrives, User::Invariant());
  1217 			if (iLocalDriveList[localDriveNumber]!=KDriveInvalid)
  1218 				{
  1219 				DEBUGPRINT2("Entry found for registered ldrive:%d -> %c:",localDriveNumber,(infoPtr->iDriveNumber+'A'));
  1220 				iMapCount++;
  1221 				}
  1222 			else
  1223 				{
  1224 				DEBUGPRINT1("Invalid LocalDriveNumber : %d",localDriveNumber);
  1225 				}
  1226 			}
  1227 		else
  1228 			{
  1229 			infoPtr->iLocalDriveNumber = KDriveInvalid;		// reset all local drives
  1230 			}
  1231 		}
  1232 		
  1233 	if (r!=KErrEof)
  1234 		{
  1235 		return((r==KErrNone)?KErrGeneral:r); // Error reading the records, or too many records in mapping file
  1236 		}
  1237 	
  1238 	// If there is the potential of a drive swap then check that the order of the entries in the mapping array
  1239 	// are consitent for this - re-order if necessary
  1240 	if (iDriveSwapCount)
  1241 		CheckAndReOrderArrayForSwapping(iMapCount);
  1242 	 	
  1243 	// Scan through the array of valid mappings - updating the the local drive list. Once, complete, write the list
  1244 	// to the File Server. (Apart from swapping internal drives, this can only be written once).
  1245 	TInt firstComp=-1;
  1246 	
  1247 	// first clear default mappings for all local drives not listed on mapping file
  1248 	TInt i;
  1249 	for(i=0;i<KMaxLocalDrives;i++)
  1250 		iLocalDriveList[i]=KDriveInvalid;
  1251 	
  1252 	// then map non composite local drives
  1253 	for (i=0;i<iMapCount;i++)
  1254 		{
  1255 		if (iDriveMappingInfo[i].iFsInfo.iFlags & FS_COMPOSITE)
  1256 			continue;	
  1257 		iLocalDriveList[iDriveMappingInfo[i].iLocalDriveNumber]=iDriveMappingInfo[i].iDriveNumber;	
  1258 		}
  1259 
  1260 	// finally map composite drives: the first is mapped to the drive letter specifed on the mapping file, the following
  1261 	// are mapped to unused drive letters. Later when they are added to the compsite mount their mappings are invalidated
  1262 	TInt drvNumber=EDriveA-1;
  1263 	for(i=0;i<iMapCount;i++)
  1264 		{
  1265 		if (iDriveMappingInfo[i].iFsInfo.iFlags & FS_COMPOSITE)
  1266 			{
  1267 			if (firstComp==-1)
  1268 				{
  1269 				firstComp=iDriveMappingInfo[i].iDriveNumber;
  1270 				iLocalDriveList[iDriveMappingInfo[i].iLocalDriveNumber]=iDriveMappingInfo[i].iDriveNumber;	
  1271 				}
  1272 			else
  1273 				{
  1274 				r=SearchForUnusedDriveNumber(drvNumber);
  1275 		        __ASSERT_ALWAYS(r==KErrNone, Panic(ELitLocalDriveMappingFail,r));
  1276 				iLocalDriveList[iDriveMappingInfo[i].iLocalDriveNumber]=drvNumber;
  1277 				}
  1278 			}
  1279 		}
  1280 
  1281 	SetFServLocalDriveMapping();
  1282 		
  1283 	
  1284 	// Scan through the array of valid mappings again - adding the FSY and any extension specified and then mounting
  1285 	// these on the drive in question.
  1286 	// Now that the mapping is written to the file server - we can't auto-detect file systems any more. Hence, don't 
  1287 	// return an error if a drive fails to mount, just keep going.
  1288 	for (i=0;i<iMapCount;i++)
  1289 		{
  1290         // Record removable drives for later mount
  1291         TLocalDriveCapsBuf caps;
  1292         TBusLocalDrive drive;
  1293         TBool changed;
  1294 		SLocalDriveMappingInfo* infoPtr = &iDriveMappingInfo[i];
  1295 		infoPtr->iRemovable = EFalse;
  1296         r = drive.Connect(iDriveMappingInfo[i].iLocalDriveNumber, changed);
  1297         if (r == KErrNone)
  1298             {
  1299             infoPtr->iCapsRetCode = r = drive.Caps(caps);
  1300 			if (r==KErrNone && caps().iDriveAtt&KDriveAttRemovable)
  1301                 {
  1302 				infoPtr->iRemovable = ETrue;
  1303                 drive.Disconnect();
  1304                 continue;
  1305                 }
  1306             drive.Disconnect();
  1307             }
  1308 
  1309 		r=MountFileSystem(iDriveMappingInfo[i]);
  1310 		if (r==KErrDisMounted)
  1311 			{
  1312 			// We have encountered a corrupt internal drive which should be swapped with another internal drive 
  1313 			SwapDriveMappings(i,iMapCount);
  1314 			i--;	// Re-attempt to mount the same drive now that the mappings are swapped		
  1315 			}
  1316 
  1317 		// If the drive is pageable, search for a ROM image file name and if found clamp it 
  1318 		// so that nothing can overwrite it
  1319 		DEBUGPRINT3("Testing if Drive %c is pageable, r %d att %08X", 'A' + iDriveMappingInfo[i].iDriveNumber, r, caps().iMediaAtt);
  1320 		if (r == KErrNone && (caps().iMediaAtt & KMediaAttPageable))
  1321 			{
  1322 			RFile file;
  1323 			RArray<TPtrC> sysFiles;
  1324 			r = SysFileNames(sysFiles);
  1325 			TInt sysFilesCount = sysFiles.Count();
  1326 			
  1327 			for (TInt n=0; n< sysFilesCount; n++)
  1328 				{
  1329 				TFileName romFilePath;
  1330 				romFilePath.Append( (TText) ('A'+iDriveMappingInfo[i].iDriveNumber) );
  1331 				romFilePath.Append(':');
  1332 				romFilePath.Append(sysFiles[n]);
  1333 
  1334 				DEBUGPRINT1("Drive %c is pageable", 'A' + iDriveMappingInfo[i].iDriveNumber);
  1335 
  1336 				r = file.Open(iFs, romFilePath, EFileRead);
  1337 				DEBUGPRINT2("Opening %S returned %d", &romFilePath, r);
  1338 				if (r == KErrNone)
  1339 					{
  1340 					RFileClamp handle;
  1341 					r = handle.Clamp(file);
  1342 					DEBUGPRINT2("Clamping %S returned %d", &romFilePath, r);
  1343 					file.Close();
  1344 					}
  1345 				}
  1346 			sysFiles.Close();
  1347 			}
  1348 
  1349 		}
  1350 	if (gCompositeMountState==1)
  1351 		LoadCompositeFileSystem(firstComp);
  1352 
  1353 	return(KErrNone);	
  1354 	}
  1355 
  1356 
  1357 /** 
  1358 Return the filenames of any "System" files on a writable drive (e.g internal MMC).
  1359 If the files are found, then they are clamped (and never unclamped) to prevent them from being overridden.
  1360 This function should be overriden by the variant if needed.
  1361 
  1362 @return KErrNotSupported, by default if the function is not overridden.
  1363 */ 
  1364 TInt TFSStartup::SysFileNames(RArray<TPtrC>& /*aFileNames*/)
  1365 	{
  1366 	return KErrNotSupported;
  1367 	}
  1368 
  1369 /**
  1370 Search for any unused drive number that has not been added to the list.
  1371 
  1372 @param aDrvNum Drive number to be checked, if used or not.
  1373 
  1374 @return  KErrNone if found one unused drive; KErrOverflow if all drives are used.
  1375 */
  1376 TInt TFSStartup::SearchForUnusedDriveNumber(TInt& aDrvNum)
  1377 	{
  1378 	TInt i;
  1379 	while(++aDrvNum<=(TInt)EDriveZ)
  1380 		{
  1381 		for(i=0;i<KMaxLocalDrives;i++)
  1382 			{
  1383 			if(iLocalDriveList[i]==aDrvNum)
  1384 				break;
  1385 			}
  1386 		if(i==KMaxLocalDrives)		// found one
  1387 			return KErrNone;
  1388 		}
  1389 	return KErrOverflow;				// all used up??
  1390 	}
  1391 
  1392 
  1393 /**
  1394 Mount a file system on a drive. Adds the FSY and any extension specified and 
  1395 then mounts these on the specified drive. Also, processes any mount flags specified.
  1396 
  1397 @param anInfo A stucture holding the drive number, the details of the FSY/ext to be mounted on it and the mount flags.
  1398 
  1399 @return KErrNone if no error, KErrDisMounted if this needs to be mounted on an alternative drive.
  1400 */
  1401 TInt TFSStartup::MountFileSystem(SLocalDriveMappingInfo& anInfo)
  1402 	{
  1403 	
  1404 	
  1405 
  1406     TInt r=KErrNone;
  1407 	TInt flags=anInfo.iFsInfo.iFlags;
  1408 	TInt drive=anInfo.iDriveNumber;
  1409 	TPtrC fsyname;	
  1410 	TPtrC objname;
  1411 	
  1412 	// If an FSY is specified, mount this on the drive in question.
  1413 	if (anInfo.iFsInfo.iFsyName && !(flags & (FS_NO_MOUNT | FS_COMPOSITE)))
  1414 		{
  1415 		fsyname.Set(anInfo.iFsInfo.iFsyName);
  1416 		r=iFs.AddFileSystem(fsyname);
  1417 		DEBUGPRINT2("AddFileSystem(%S) -> %d",&fsyname,r);
  1418 		if (r!=KErrNone && r!=KErrAlreadyExists)
  1419 			return(r);
  1420 
  1421 		if (flags & FS_NOT_RUGGED)
  1422 			{
  1423 			r = iFs.SetStartupConfiguration(ESetRugged, (TAny*)drive, (TAny*)EFalse);
  1424 			iRuggedFileSystem = 0;
  1425 			}
  1426 
  1427 		objname.Set((anInfo.iFsInfo.iObjName) ? anInfo.iFsInfo.iObjName : anInfo.iFsInfo.iFsyName);
  1428 		TBool isSync=(flags & FS_SYNC_DRIVE);
  1429 		if (anInfo.iFsInfo.iExtName)
  1430 			{
  1431 			TPtrC extname(anInfo.iFsInfo.iExtName);
  1432 			r=iFs.AddExtension(extname);
  1433 			if (r==KErrNone || r==KErrAlreadyExists)
  1434 				r=iFs.MountFileSystem(objname,extname,drive,isSync);
  1435 			}
  1436 		else
  1437 			r=iFs.MountFileSystem(objname,drive,isSync);
  1438 				
  1439 		DEBUGPRINT4("MountFileSystem(%S) on drive %c: -> %d (sync=%d)",&objname,(drive+'A'),r,isSync);
  1440 		iUnmountedDriveBitmask&=~(0x01<<(anInfo.iLocalDriveNumber));
  1441 		}
  1442 	
  1443 	// Process the mount flags	
  1444 	DEBUGPRINT1("FSI flags %08x",flags);
  1445 	TInt cf;	
  1446 	if ((cf=HandleCustomMountFlags(r,flags,anInfo.iSpare,drive))!=KErrNone)
  1447 		return(cf);	
  1448 
  1449 	if (flags & FS_COMPOSITE)
  1450 		if (anInfo.iFsInfo.iFsyName && TPtrC(anInfo.iFsInfo.iFsyName).CompareF(KEcomp))
  1451 			LoadCompositeFileSystem(anInfo);
  1452 		else
  1453 			LoadCompositeFileSystem(drive);
  1454 	// Handle format related flags	
  1455 	if (flags & FS_FORMAT_ALWAYS)
  1456 		r=FormatDrive(drive);
  1457 	if ((flags & FS_FORMAT_COLD) && iColdStart)
  1458 		r=FormatDrive(drive);
  1459 	if (r==KErrCorrupt && (flags & FS_FORMAT_CORRUPT))
  1460 		r=FormatDrive(drive);	
  1461 	
  1462     
  1463     //-- running ScanDrive on Rugged FAT volumes. "Rugged FAT" and "ScanDrive" are counterparts. 
  1464     //-- 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
  1465     //-- 2. Vice versa, running ScanDrive on "non-rugged FAT" doesn't make any sense, it is jsut waste of time.
  1466     //-- Thus: if the volume is detected as "Rugged FAT", force running ScanDrive on it; otherwise ignore FS_SCANDRIVE flag
  1467 #if !defined(__X86__)	
  1468 	if(r==KErrNone)
  1469         {
  1470         TText driveLetter=(TText)(drive+'A');
  1471 		TBuf<3> driveDes=_L("?:\\");
  1472 		driveDes[0]=driveLetter;
  1473 
  1474         if(iRuggedFileSystem)
  1475             {//-- the volume has rugged FAT, force ScanDrive
  1476             
  1477             if(!(flags & FS_SCANDRIVE))
  1478                 {//-- no FS_SCANDRIVE flag, this is obvious misconfiguration
  1479                 if(objname.CompareF(_L("FAT")) == 0)
  1480                     {
  1481                     DEBUGPRINT1("### !!!! WARNING!!! Drive %S has RuggedFAT, but no FS_SCANDRIVE flag in estart.txt", &driveDes);
  1482                     DEBUGPRINT( "### !!!! Forcing ScanDrive. Check that the drive is configured properly !!!");
  1483                     }
  1484                 }
  1485             
  1486             iFs.ScanDrive(driveDes);
  1487             }
  1488         else
  1489             {//-- the volume doesn't have rugged FAT 
  1490             if(flags & FS_SCANDRIVE)
  1491                 {//-- FS_SCANDRIVE flag is set for non-rugged-FAT drive. don't run ScanDrive 
  1492                 DEBUGPRINT1("### !!!! WARNING!!! Drive %S has NON-Rugged FAT, but FS_SCANDRIVE flag is set in estart.txt", &driveDes);
  1493                 DEBUGPRINT( "### !!!! SKipping ScanDrive. Check that the drive is configured properly !!!");
  1494                 }
  1495             }
  1496         }  
  1497 
  1498 #endif
  1499 	
  1500 	// Handle swap on corrupt or dismount on corrupt	
  1501 	if (r==KErrCorrupt && ((flags & FS_DISMNT_CORRUPT) || (flags & FS_SWAP_CORRUPT))) 
  1502 //	if (((flags & FS_DISMNT_CORRUPT) || (flags & FS_SWAP_CORRUPT))) // Testing swap mode - always swaps
  1503 		{
  1504 		if (objname.Ptr())
  1505 			iFs.DismountFileSystem(objname,drive);
  1506 			
  1507 		if (flags & FS_SWAP_CORRUPT)
  1508 			{
  1509 			anInfo.iFsInfo.iFlags&=~FS_SWAP_CORRUPT; 	// Mustn't try to swap again the next time
  1510 			r=KErrDisMounted;						 	// Signal that this needs to be re-mounted on another drive
  1511 			}	
  1512 		}
  1513 	return(r);
  1514 	}
  1515 
  1516 #if !defined(AUTODETECT_DISABLE)
  1517 const TInt KMaxFSInfoTableEntries=8;	
  1518 /**
  1519 Standard file system info. array - used when auto-detecting an appropraite FSY for a local drive. In this scheme, the local
  1520 drive capabilities and partition type information is examined to determine an appropraite FSY for the drive. Each entry
  1521 contains an FSY detection function together with the corresponding information for that particular FSY configuration. This
  1522 information includes the FSY/ext name string pointers and mounting flags. Each detection function should uniquely identify
  1523 its associated FSY configuration.
  1524 */
  1525 LOCAL_D const SFileSystemInfo FileSystems[KMaxFSInfoTableEntries] =
  1526 	{
  1527 		{DetectELocal,      {_S("elocal"),       _S("fat"),      0,             FS_SCANDRIVE}},
  1528 		{DetectIRam,        {_S("elocal"),       _S("fat"),      0,             FS_FORMAT_COLD|FS_SYNC_DRIVE}},
  1529 		{DetectFtl,         {_S("elocal"),       _S("fat"),      0,				FS_FORMAT_CORRUPT|FS_SCANDRIVE}},
  1530 		{DetectRofs,        {_S("erofs"),        _S("rofs"),     0,             FS_DISMNT_CORRUPT}},
  1531 		{DetectComposite,	{0,      			 0,    			 0,       		FS_COMPOSITE}},
  1532 		{DetectEneaLFFS,    {_S("elffs"),        _S("lffs"),     0,             FS_FORMAT_CORRUPT}},
  1533 		{DetectIso9660,     {_S("iso9660"),      0,              0,             0}},
  1534 		{DetectNtfs,        {_S("ntfs"),         0,              0,             0}},		
  1535 	};
  1536 
  1537 /**
  1538 Return the next entry from the standard file system info array - used when auto-detecting an FSY for a local drive.
  1539 Override this function when altering or extending the standard file system info. array.
  1540 
  1541 @param anInfo	Address of a pointer to a stucture to hold the returned mapping settings, 
  1542 				FSY/ext name string pointers and mounting flags.
  1543 @param aPos		The current position within the array. The caller is responsible to 
  1544 				initializing and incrementing this.
  1545 
  1546 @return	KErrNone if no error, KErrNotFound if the end of the array is reached.
  1547 */	
  1548 TInt TFSStartup::GetNextStandardFSInfoEntry(const SFileSystemInfo** anEntry,TInt aPos)
  1549 	{
  1550 
  1551 	if (aPos<KMaxFSInfoTableEntries)
  1552 		{
  1553 		*anEntry=&FileSystems[aPos];
  1554 		return(KErrNone);
  1555 		}
  1556 	else
  1557 		return(KErrNotFound);	
  1558 	}	
  1559 
  1560 /**
  1561 Detect the appropraite FSY configuration for a particular local drive. This is 
  1562 achieved by reading the drives capabilities and partition information and using 
  1563 this to determine an appropraite config.
  1564 
  1565 @param aLocalDriveNumber	The number of the local drive .
  1566 @param anInfo				A stucture to hold the returned mapping settings, 
  1567 							FSY/ext name string pointers and mounting flags.
  1568 
  1569 @return KErrNone if successful, KErrNotFound if an appropriate file system isn't found or any other error.
  1570 */	
  1571 TInt TFSStartup::DetectFileSystem(TInt aLocalDriveNumber,SLocalDriveMappingInfo& anInfo)
  1572 	{
  1573 	
  1574 	DEBUGPRINT1("DetectFileSystem ldrive:%d",aLocalDriveNumber);
  1575 	TLocalDriveCapsV2 caps;
  1576 	TPckg<TLocalDriveCapsV2> capsBuf(caps);
  1577 	RLocalDrive ld;
  1578 	TBool changed;
  1579 	TInt r = ld.Connect(aLocalDriveNumber, changed);
  1580 	DEBUGPRINT1("Connect -> %d", r);
  1581 	if (r!=KErrNone)
  1582 		return(r);
  1583 	TInt cr=ld.Caps(capsBuf);
  1584 	DEBUGPRINT1("Caps -> %d", cr);
  1585 	const SFileSystemInfo* fsi=NULL;
  1586 	for (TInt i=0 ; (r=GetNextStandardFSInfoEntry(&fsi,i))==KErrNone ; i++)
  1587 		{
  1588 		TInt d=(*fsi->iDetect)(ld,cr,caps);
  1589 		DEBUGPRINT2("FS:%d Detect -> %d",i,d);
  1590 		if (d<KErrNone)
  1591 			continue;
  1592 		if (d>KErrNone)
  1593 			{
  1594 			d-=KFsDetectMappingChangeReturnOffset;
  1595 			if (d>=EDriveA && d<=EDriveZ) 
  1596 				iLocalDriveList[aLocalDriveNumber]=d;
  1597 			}
  1598 		TInt drive=iLocalDriveList[aLocalDriveNumber];		
  1599 		anInfo.iDriveNumber=drive;
  1600 		anInfo.iLocalDriveNumber=aLocalDriveNumber;
  1601 		anInfo.iFsInfo=fsi->iFsInfo;
  1602 		anInfo.iSpare=0;
  1603 		break;
  1604 		}
  1605 	ld.Close();
  1606 	return(r);
  1607 	}
  1608 
  1609 /**
  1610 For each registered local drive on the system detect an appropriate FSY configuration 
  1611 and attempt to mount this on the drive concerned.
  1612 
  1613 @return	Always returns KErrNone.
  1614 */
  1615 TInt TFSStartup::DetectAndMountFileSystems()
  1616 	{
  1617 	
  1618 	InitCompositeFileSystem();
  1619 	
  1620 	// Determine an appropriate FSY configuration for each registered local drive
  1621 	TInt i;
  1622 	DEBUGPRINT("DetectAndMountFileSystems");
  1623 	iMapCount=0;
  1624 	SLocalDriveMappingInfo* infoPtr;
  1625 	for (i=0;i<KMaxLocalDrives;++i)
  1626 		{
  1627 		if(iLocalDriveList[i]!=KDriveInvalid)
  1628 			{
  1629 			infoPtr=&iDriveMappingInfo[iMapCount];
  1630 			if (DetectFileSystem(i,*infoPtr)==KErrNone)
  1631 				{
  1632 				DEBUGPRINT3("Entry found for registered ldrive: %2d->%c: (%s)",i,(infoPtr->iDriveNumber+'A'),infoPtr->iFsInfo.iFsyName);
  1633 				iMapCount++;
  1634 				}
  1635 			}
  1636 		}
  1637 	
  1638 	// Scan through the array of valid mappings - updating the the local drive list. Once, complete, write the list
  1639 	// to the File Server (can only be written once).
  1640 	for (i=0;i<iMapCount;i++)	
  1641 		iLocalDriveList[iDriveMappingInfo[i].iLocalDriveNumber]=iDriveMappingInfo[i].iDriveNumber;	
  1642 	SetFServLocalDriveMapping();	
  1643 	
  1644 	// Scan through the array of valid mappings again - adding the FSY and any extension specified and then mounting
  1645 	// these on the drive in question
  1646 	for (i=0;i<iMapCount;i++)
  1647         {
  1648         // Record removable drives for later mount
  1649         TLocalDriveCapsBuf caps;
  1650         TBusLocalDrive drive;
  1651         TBool changed;
  1652 		SLocalDriveMappingInfo* infoPtr = &iDriveMappingInfo[i];
  1653 		infoPtr->iRemovable = EFalse;
  1654         TInt r = drive.Connect(iDriveMappingInfo[i].iLocalDriveNumber, changed);
  1655         if (r == KErrNone)
  1656             {
  1657             infoPtr->iCapsRetCode = r = drive.Caps(caps);
  1658 			TInt sockNum;
  1659 			if (r==KErrNone && (caps().iDriveAtt&KDriveAttRemovable || drive.IsRemovable(sockNum)))
  1660                 {
  1661 				infoPtr->iRemovable = ETrue;
  1662                 drive.Disconnect();
  1663                 continue;
  1664                 }
  1665             drive.Disconnect();
  1666             }
  1667 
  1668 		r=MountFileSystem(iDriveMappingInfo[i]);
  1669 		if (r==KErrDisMounted)
  1670 			{
  1671 			// We have encountered a corrupt internal drive which should be swapped with another internal drive 
  1672 			SwapDriveMappings(i,iMapCount);
  1673 			i--;	// Re-attempt to mount the same drive now that the mappings are swapped		
  1674 			}
  1675         }
  1676 
  1677     return(KErrNone);	
  1678 	}
  1679 #endif	
  1680 
  1681 #if defined(_LOCKABLE_MEDIA)
  1682 /**
  1683 Initialise the local media password store with contents of a file.
  1684 
  1685 @param aFile	The file used to initialize the store. Must already be opened for 
  1686 				read access in EFileStreamText mode.  
  1687 
  1688 @return KErrNone if successful, KErrNoMemory if heap is full, otherwise one of the other system-wide error codes.
  1689 */
  1690 TInt TFSStartup::WriteLocalPwStore(RFile& aFile)
  1691 //
  1692 // Initialise local media password store with contents of aFile
  1693 //
  1694 	{
  1695 	
  1696 	DEBUGPRINT("WriteLocalPwStore");
  1697 
  1698 	TInt size;
  1699 	TInt r=aFile.Size(size);
  1700 	if(r!=KErrNone || size==0)
  1701 		return(r);
  1702 	HBufC8* hBuf=HBufC8::New(size);
  1703 	if(hBuf==NULL)
  1704 		return(KErrNoMemory);
  1705 	TPtr8 pBuf=hBuf->Des();
  1706 	r=aFile.Read(pBuf);
  1707 	if(r==KErrNone)
  1708 		{
  1709 		TBusLocalDrive TBLD;
  1710 		TBool TBLDChangedFlag;
  1711 
  1712 		for (TInt i=0; i<iMapCount; i++)
  1713 			{
  1714 			SLocalDriveMappingInfo* infoPtr = &iDriveMappingInfo[i];
  1715 			DEBUGPRINT3("drive %d: removable %d capsret %d", i, infoPtr->iRemovable, infoPtr->iCapsRetCode);
  1716 			if (infoPtr->iRemovable || infoPtr->iCapsRetCode == KErrNotReady)
  1717 				{
  1718 				r = TBLD.Connect(iDriveMappingInfo[i].iLocalDriveNumber, TBLDChangedFlag);
  1719 				if(r==KErrNone)
  1720 					{
  1721 					r = TBLD.WritePasswordData(pBuf);
  1722 					DEBUGPRINT2("WritePasswordData on drive %d returned %d", i, r);
  1723 					TBLD.Disconnect();
  1724 					// ignore error if media not ready (it MAY not be a removable drive)
  1725 					if (r != KErrNone && infoPtr->iCapsRetCode == KErrNotReady)
  1726 						r = KErrNone;
  1727 					}
  1728 				}
  1729 			}
  1730 		}
  1731 	delete hBuf;
  1732 	return(r);
  1733 	}
  1734 
  1735 /**	
  1736 Attempt to initilise the local media password store. This allows locked media devices 
  1737 (e.g. password protected MMC cards) to be accessed without notifier.
  1738 
  1739 @return KErrNone if successful otherwise one of the other system-wide error codes.
  1740 */	
  1741 TInt TFSStartup::InitializeLocalPwStore()
  1742 	{
  1743 	// Attempt to initilise the local media password store
  1744 	// Allows locked device to be accessed without notifier
  1745 
  1746 	DEBUGPRINT("InitializeLocalPwStore");
  1747 
  1748 	RFile f;
  1749 	TBuf<sizeof(KMediaPWrdFile)> mediaPWrdFile(KMediaPWrdFile);
  1750 	mediaPWrdFile[0] = (TUint8) RFs::GetSystemDriveChar();
  1751 	TInt r=f.Open(iFs,mediaPWrdFile,EFileShareExclusive | EFileStream | EFileRead);
  1752 	if (r==KErrNone)
  1753 		{
  1754 		r=WriteLocalPwStore(f);
  1755 		__ASSERT_DEBUG(r == KErrNone || r == KErrCorrupt || r == KErrNotReady, Panic(ELitInitLocalPwStoreFail,r));
  1756 		f.Close();
  1757 		}
  1758 	return(r);	
  1759 	}		
  1760 #endif
  1761 
  1762 #ifdef LOAD_PATCH_LDD
  1763 /**
  1764 Find any patch LDDs and load them.
  1765 
  1766 @panic ESTART_8 0; if creation of trap handler failed.
  1767 @panic ESTART_9 Error_Code;	if loading of LDD failed.
  1768 				Error_Code is the error code returned by User::LoadLogicalDevice().
  1769 */
  1770 void TFSStartup::LoadPatchLDDs()
  1771 	{
  1772 #if defined(__EPOC32__)	
  1773 	// Load an LDD to patch any bugs in the ROM
  1774 	// This will always return an error - ignore it
  1775 	_LIT(KLitPatchBootLdd,"Z:\\Sys\\Bin\\BOOT.LDD");
  1776 	TInt r;
  1777 	User::LoadLogicalDevice(KLitPatchBootLdd);
  1778 
  1779 	//	Install a trap handler - fs.GetDir calls functions which might leave
  1780 	CTrapCleanup* trapHandler=CTrapCleanup::New();
  1781 	__ASSERT_ALWAYS(trapHandler!=NULL,Panic(ELitCreateTrapHandlerFail,0));
  1782 
  1783 	//	Find any patch ldds and load them - files with the .SYS extension and second uid KLogicalDeviceDriverUid
  1784 	//	and third uid KPatchLddUid (0x100000CC, BOOT.LDD should probably be checked for this too)
  1785 	CDir* patchList=NULL;
  1786 	_LIT(KLitPatchSysLdd,"?:\\Sys\\Bin\\*.SYS");
  1787 	TBuf<sizeof(KLitPatchSysLdd)> litPatchSysLdd(KLitPatchSysLdd);
  1788 	litPatchSysLdd[0] = (TUint8) RFs::GetSystemDriveChar();
  1789 	if (iFs.GetDir(litPatchSysLdd,(KEntryAttSystem|KEntryAttAllowUid),ESortByName,patchList)==KErrNone)
  1790 		{
  1791 		patchList->Sort(ESortByName);
  1792 		TInt i;
  1793 		for (i=0;i<patchList->Count();i++)
  1794 			{
  1795 			TEntry& entry=(*patchList)[i];
  1796 			if (entry[1]==KLogicalDeviceDriverUid && entry[2].iUid==KPatchLddUidValue)
  1797 				{
  1798 				r=User::LoadLogicalDevice(entry.iName);
  1799 				__ASSERT_DEBUG(r==KErrNone,Panic(ELitLoadSysLddsFail,r));
  1800 				}
  1801 			}
  1802 		}
  1803 	delete trapHandler;
  1804 #endif	
  1805 	}	
  1806 #endif	
  1807 
  1808 /**
  1809 Try to add both the ROFS and Composite file systems.
  1810 
  1811 @return KErrNone if successful, KErrNotFound if either fail to be added.
  1812 */
  1813 TInt TFSStartup::InitCompositeFileSystem()
  1814 	{
  1815 	DEBUGPRINT("InitCompositeFileSystem");
  1816 	TInt r=iFs.AddFileSystem(KRofs);
  1817 	if (r==KErrNone || r==KErrAlreadyExists)
  1818 		{
  1819 		DEBUGPRINT("ROFS is present");
  1820 		r=iFs.AddFileSystem(KCompfs);
  1821 		if (r==KErrNone || r==KErrAlreadyExists)
  1822 			{
  1823 			gMountComposite=ETrue;
  1824 			gMountRofsAlone=EFalse;
  1825 			DEBUGPRINT("Comp FS is present");
  1826 			return(KErrNone);
  1827 			}
  1828 		}
  1829 	else
  1830 		gMountRofsAlone=EFalse;			
  1831 
  1832 	return(KErrNotFound);
  1833 	}
  1834 
  1835 /**
  1836 Mount the composite file system on the specified drive.
  1837 
  1838 @param The number of the drive on which the composite FSY is to be loaded on. 
  1839 
  1840 @panic ESTART_16 Error_Code; If unable to get file system name on the drive.
  1841 				 Error_Code is the error code returned by RFs::FileSystemName().
  1842 @panic ESTART_15 Error_Code; If unable to mount composite file system.
  1843 				 Error_Code is the error code returned by RFs::SwapFileSystem().
  1844 */
  1845 _LIT(KCompositeName,"Composite");
  1846 void TFSStartup::LoadCompositeFileSystem(TInt aDrive)
  1847 	{
  1848 	
  1849 	if (gMountComposite)
  1850 		{
  1851 		DEBUGPRINT1("LoadCompositeFileSystem on %c:",(aDrive+'A'));
  1852 		TBuf<16> buf;
  1853 		TInt r=iFs.FileSystemName(buf,aDrive);
  1854 		DEBUGPRINT1("Read current FSY returns %d",r);
  1855 		__ASSERT_ALWAYS(r==KErrNone, Panic(EFsNameFail,r));
  1856 		__ASSERT_ALWAYS(buf!=KCompositeName, Panic(EFsNameFail,r));
  1857 		
  1858 		DEBUGPRINT1("Swap composite for %S",&buf);
  1859 		r=iFs.SwapFileSystem(buf,_L("Composite"),aDrive);
  1860 		DEBUGPRINT1("Swap file system returned %d", r);
  1861 		__ASSERT_ALWAYS(r==KErrNone, Panic(ECompMountFsFail,r));
  1862 		gCompositeMountState=ESwapped;
  1863 		}
  1864 	}
  1865 /**
  1866 Adds a local drive to the composite filesystem.
  1867 
  1868 @param anInfo A stucture holding mounting flags, drive number info.
  1869 
  1870 @panic ESTART_15 -11; If composite mount file already exist.
  1871 */
  1872 void TFSStartup::LoadCompositeFileSystem(SLocalDriveMappingInfo& anInfo)
  1873 	{
  1874 		
  1875 	if (gMountComposite)
  1876 		{
  1877 		__ASSERT_ALWAYS(gCompositeMountState<2, Panic(ECompMountFsFail,KErrAlreadyExists));
  1878 
  1879 		TPtrC fsyname;
  1880 		TBool sync = (anInfo.iFsInfo.iFlags & FS_SYNC_DRIVE)!=0;
  1881 		
  1882 		fsyname.Set(anInfo.iFsInfo.iFsyName);
  1883 		TInt r=iFs.AddFileSystem(fsyname);
  1884 		DEBUGPRINT2("AddFileSystem(%S) -> %d",&fsyname,r);
  1885 		__ASSERT_ALWAYS(r==KErrNone || r==KErrAlreadyExists, Panic(ECompMountFsFail,r));		
  1886 				
  1887 		TPtrC objname;
  1888 		objname.Set((anInfo.iFsInfo.iObjName) ? anInfo.iFsInfo.iObjName : anInfo.iFsInfo.iFsyName);
  1889 		DEBUGPRINT4("LoadCompositeFileSystem on %c: with drive %i (%S) included. Sync=%d",(anInfo.iDriveNumber+'A'),anInfo.iLocalDriveNumber,&objname, anInfo.iFsInfo.iFlags);
  1890 		r=iFs.AddCompositeMount(objname,anInfo.iLocalDriveNumber,anInfo.iDriveNumber, sync);
  1891 		DEBUGPRINT1("AddCompositeMount returned %d", r);
  1892 		if (r==KErrNone)
  1893 			gCompositeMountState=EHasMounts;
  1894 		}
  1895 	}
  1896 
  1897 
  1898 /**
  1899 Initialize the local drives.It loads the relevant File Systems (FSYs), 
  1900 File Server extensions (FXTs) and mounts these on the appropriate drives. 
  1901 This involves mapping local drives to particular drive letters. 
  1902 First it attempts to open the local drive mapping file ESTART.TXT.If this file is 
  1903 found then ESTART loads this and attempts to apply the mapping contained within it. 
  1904 If a mapping file is not found then it attempts to automatically detect the most 
  1905 appropriate configuration for each local drive registered. 
  1906 Hence, if it has been necessary to customize ESTART solely to provide a custom set 
  1907 of local drive mappings then the generic ESTART can now be used - in conjunction 
  1908 with a platform specific version of the local drive mapping file: ESTART.TXT. 
  1909 However The entire local drive initialisation sequence provided by the generic version 
  1910 of ESTART can be overridden (while possibly re-using some of the services provided by 
  1911 the generic version).
  1912 
  1913 @return KErrNone if successful.
  1914 
  1915 @panic ESTART_11 Error_Code; If drive mapping file was not found and autodetect was not enabled.
  1916 				 Error_Code is the error code returned by ProcessLocalDriveMappingFile().
  1917 */
  1918 TInt TFSStartup::LocalDriveInit()
  1919 	{	
  1920 	
  1921 	TInt i;
  1922     for(i=0;i<KMaxLocalDrives;i++)
  1923 		iDriveMappingInfo[i].iLocalDriveNumber=KDriveInvalid;		// reset all local drives
  1924 
  1925 	TInt r=ProcessLocalDriveMappingFile();
  1926 	if (r!=KErrNone)
  1927 #if !defined(AUTODETECT_DISABLE)		
  1928 		DetectAndMountFileSystems();
  1929 #else
  1930 		Panic(ELitDriveMappingFileFail,r);
  1931 #endif		
  1932 
  1933 	SetSystemDrive();
  1934 		
  1935 #if defined(_LOCKABLE_MEDIA)	
  1936 	InitializeLocalPwStore();	
  1937 #endif	
  1938 
  1939 #ifdef LOAD_PATCH_LDD
  1940 	LoadPatchLDDs();
  1941 #endif	
  1942 	
  1943 	// Notify file server that local fs initialisation complete
  1944 	TRequestStatus status;
  1945 	iFs.StartupInitComplete(status);
  1946 	User::WaitForRequest(status);
  1947 	DEBUGPRINT1("StatusInitComplete r=%d",status.Int());	
  1948 	
  1949 	return(KErrNone);
  1950 	}
  1951 
  1952 /**
  1953 Get system startup mode. Licensees should override one of these two GetStartupMode 
  1954 functions to provide mechanism of getting startup mode. Startup mode then is put in iStartupMode.
  1955 
  1956 @return KErrNone if successful.
  1957 
  1958 @see TFSStartup::GetStartupModeFromFile()
  1959 */
  1960 TInt TFSStartup::GetStartupMode()
  1961     {
  1962     return KErrNone;
  1963     }
  1964 
  1965 /**
  1966 Get system startup mode from file after file server startup.
  1967 
  1968 @return KErrNone if successful.
  1969 
  1970 @see  TFSStartup::GetStartupMode()
  1971 */
  1972 TInt TFSStartup::GetStartupModeFromFile()
  1973     {
  1974     return KErrNotSupported;
  1975     }
  1976 
  1977 /**
  1978 Start the rest of the system. Try to find sysstart.exe and launch it. 
  1979 If failed to find it launch window server instead. This path is deprecated.
  1980 
  1981 @return KErrNone if successful.
  1982 
  1983 @panic ESTART_18 Error_Code; If getting startup mode fails.
  1984 				 Error_Code is the error returned by GetStartupModeFromFile().
  1985 @panic ESTART_14 Error_Code; If set for startup Mode fails.
  1986 				 Error_Code is the error returned by RProperty::Set()
  1987 @panic ESTART_19 Error_Code; If fails to lunch system agent.
  1988 				 Error_Code is the error returned by StartSysAgt2()
  1989 @panic ESTART_17 -1; If unable to start windows server.
  1990 */	
  1991 TInt TFSStartup::StartSystem()
  1992 	{
  1993 	// Get startup mode when need to access file server
  1994 	TInt r = GetStartupModeFromFile();
  1995 	if (r != KErrNotSupported)
  1996         {
  1997         __ASSERT_ALWAYS(r==KErrNone, Panic(EStartupModeFail,r));
  1998         // Update startup mode property value
  1999         r = RProperty::Set(KUidSystemCategory, KSystemStartupModeKey, iStartupMode);
  2000         __ASSERT_ALWAYS(r==KErrNone, Panic(EPropertyError,r));
  2001         }
  2002 
  2003     // Launch system starter in system path
  2004 	RProcess ws;
  2005 	r=ws.Create(KSystemStateManager, KNullDesC);
  2006 	if (r!=KErrNone)
  2007 		{
  2008 		r=ws.Create(KSystemStarterName, KNullDesC);
  2009 		if (r!=KErrNone)
  2010 			{
  2011 			r = StartSysAgt2();
  2012 			if (r != KErrNone && r != KErrNotFound)
  2013 				Panic(ESysAgentFail,r);
  2014 
  2015 			// Start the window server if failed starting up system starter
  2016 			TDriveList list;
  2017 			iFs.DriveList(list);
  2018 			if (!CreateServer(list,KWindowServerRootName1))
  2019     		Panic(ELitNoWS,KErrNotFound);			
  2020 			}
  2021 		else
  2022 			{
  2023 #ifdef SYMBIAN_ESTART_OUTPUT_BOOT_TIME
  2024 			TRequestStatus status;
  2025 			ws.Logon(status);
  2026 			ws.Resume();
  2027 			//-- wait for SystemStarter to finish and then output the number of ticks since boot
  2028 			//-- !! N.B on some systems SystemStarter process never finish, so the "status" never gets completed.
  2029             //-- !! In this case it is worth trying Rendezvous(); because it usually call it.
  2030 
  2031             User::WaitForRequest(status);
  2032 			TUint tickCount = User::TickCount();
  2033 			RDebug::Printf("Boot time ticks %d (%d ms)\n", tickCount, tickCount*1000/64);
  2034 #else
  2035 
  2036 			ws.Resume();
  2037 #endif	// SYMBIAN_ESTART_OUTPUT_BOOT_TIME
  2038 			ws.Close();
  2039 			}
  2040 	    }
  2041     else
  2042         {
  2043 		TRequestStatus status;
  2044 		ws.Rendezvous(status);
  2045 		ws.Resume();
  2046 		User::WaitForRequest(status);
  2047 #ifdef SYMBIAN_ESTART_OUTPUT_BOOT_TIME
  2048 		// wait for SystemStateManager to finish and then output the number of ticks since boot
  2049 		TUint tickCount = User::TickCount();
  2050 		RDebug::Printf("Boot time ticks %d (%d ms)\n", tickCount, tickCount*1000/64);
  2051 #else
  2052 		// System state manager may not exit on completion.
  2053 		if (ws.ExitType() != EExitKill && ws.ExitType() != EExitPending)
  2054 			User::Panic(_L("SysState died"),status.Int());
  2055 #endif	// SYMBIAN_ESTART_OUTPUT_BOOT_TIME
  2056        	ws.Close();
  2057         }
  2058 
  2059 	return(KErrNone);
  2060 	}
  2061 
  2062 /**
  2063 File system startup class constructor
  2064 */	
  2065 TFSStartup::TFSStartup()
  2066 	{
  2067 	iStartupMode=0;
  2068 	iMuid=0;
  2069 	iTotalSupportedDrives=0;
  2070 	iRuggedFileSystem=0;
  2071 	iRegisteredDriveBitmask=0;
  2072 	iDriveSwapCount=0;	
  2073 	iColdStart=EFalse;
  2074 	iUnmountedDriveBitmask=0;
  2075     iMapFile = NULL;
  2076 	}
  2077 
  2078 /**
  2079 Initilize the file system startup class. Checks for the Capability of the process. 
  2080 Sets the termination effect of current and subsequently created thread on the 
  2081 owning process. Publishes startup mode property. Ensures HAL memory allocation is 
  2082 done and connects to the file server.
  2083 
  2084 @panic ESTART_14 Error_Code; If either the capability is not present or unable to define or set the property.
  2085 				 Error_Code is the error code returned by RProcess().HasCapability() or 
  2086 				 RProperty::Define() or RProperty::Set().
  2087 @panic ESTART_18 Error_Code; If unable to get startup mode.
  2088 				 Error_Code is the error code returned by GetStartupMode().
  2089 @panic ESTART_3  Error_Code; If HAL initialization fails.
  2090 				 Error_Code is the error code returned by HAL::Get().
  2091 @panic ESTART_4  Error_Code; If unable to connect to file server.
  2092 				 Error_Code is the error code returned by RFs::Connect().
  2093 @panic ESTART_7  Error_Code; If unable to fetch drive information.
  2094 				 Error_Code is the error code returned by UserHal::DriveInfo().
  2095 */
  2096 void TFSStartup::Init()
  2097 	{
  2098 #ifndef SYMBIAN_EXCLUDE_ESTART_DOMAIN_MANAGER
  2099 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
  2100 	const char myDiagMsg[] = __PLATSEC_DIAGNOSTIC_STRING("Capability Check Failure");
  2101 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
  2102 	TBool cap=RProcess().HasCapability(ECapabilityPowerMgmt, __PLATSEC_DIAGNOSTIC_STRING(myDiagMsg));
  2103     __ASSERT_ALWAYS(cap, Panic(EPropertyError, cap));
  2104 #endif
  2105 	
  2106 	User::SetProcessCritical(User::ESystemCritical);
  2107 	User::SetCritical(User::ESystemCritical);
  2108 
  2109 	// Get boot mode without need to access file server
  2110 	TInt r = GetStartupMode();
  2111     __ASSERT_ALWAYS(r==KErrNone, Panic(EStartupModeFail,r));
  2112 
  2113     // Publish startup mode property
  2114     _LIT_SECURITY_POLICY_PASS(readPolicy);
  2115     _LIT_SECURITY_POLICY_C1(writePolicy, ECapabilityWriteDeviceData);
  2116     r = RProperty::Define(KUidSystemCategory, KSystemStartupModeKey, RProperty::EInt, readPolicy, writePolicy);
  2117     __ASSERT_ALWAYS(r==KErrNone, Panic(EPropertyError, r));
  2118     r = RProperty::Set(KUidSystemCategory, KSystemStartupModeKey, iStartupMode);
  2119     __ASSERT_ALWAYS(r==KErrNone, Panic(EPropertyError, r));
  2120 
  2121     r=HAL::Get(HAL::EMachineUid,iMuid);		// make sure HAL memory allocation is done
  2122     __ASSERT_ALWAYS(r==KErrNone, Panic(ELitHALFail, r));
  2123 
  2124 	r=iFs.Connect();
  2125     __ASSERT_ALWAYS(r==KErrNone, Panic(ELitConnectFsFail1, r));
  2126 
  2127 	TDriveInfoV1Buf driveInfo;
  2128 	r=UserHal::DriveInfo(driveInfo);
  2129 	__ASSERT_ALWAYS(r==KErrNone,Panic(ELitFSInitDriveInfoFail,r));
  2130 	iTotalSupportedDrives=driveInfo().iTotalSupportedDrives;
  2131 	iRuggedFileSystem=driveInfo().iRuggedFileSystem;
  2132 	iRegisteredDriveBitmask=driveInfo().iRegisteredDriveBitmask;
  2133 
  2134 	TUint registeredDriveBitmask=iRegisteredDriveBitmask;
  2135 	for (TInt i=0;i<KMaxLocalDrives;i++)
  2136 		{
  2137 		if (registeredDriveBitmask & 0x01)
  2138 			iLocalDriveList[i]=DefaultLocalDrive(i); 
  2139 		else
  2140 			iLocalDriveList[i]=KDriveInvalid;
  2141 		registeredDriveBitmask >>= 1;
  2142 		}
  2143 	iUnmountedDriveBitmask=iRegisteredDriveBitmask;	
  2144 		
  2145 	TMachineStartupType reason;
  2146 	UserHal::StartupReason(reason);
  2147 	if (reason==EStartupCold || reason==EStartupColdReset)
  2148 		iColdStart=ETrue;	
  2149 	}	
  2150 	
  2151 /**
  2152 Mount all removable drives.
  2153 
  2154 @return KErrNone if successful.
  2155 */
  2156 TInt TFSStartup::MountRemovableDrives()
  2157     {
  2158     DEBUGPRINT("TFSStartup::MountRemovableDrives");
  2159 
  2160 	for (TInt i=0;i<iMapCount;i++)
  2161 		{
  2162 		SLocalDriveMappingInfo* infoPtr = &iDriveMappingInfo[i];
  2163 		if (!infoPtr->iRemovable)
  2164 			continue;
  2165         TInt r = MountFileSystem(iDriveMappingInfo[i]);
  2166         DEBUGPRINT2("Mount drive (%c) -> %d",'A'+iDriveMappingInfo[i].iDriveNumber,r);
  2167 		if (r==KErrDisMounted)
  2168 			{
  2169 			// We have encountered a corrupt internal drive which should be swapped with another internal drive 
  2170 			SwapDriveMappings(i,iMapCount);
  2171 			i--;	// Re-attempt to mount the same drive now that the mappings are swapped		
  2172 			}
  2173 		}
  2174     return KErrNone;
  2175     }
  2176 
  2177 /**
  2178 This is the main execution function which is responsible to start the File system. 
  2179 It sets the default Locale properties. Initializes all the local drives, HAL and 
  2180 creates the domain manager process. It also loads the locale and mounts all the
  2181 removable drives.
  2182 
  2183 @return KErrNone if successful.
  2184 
  2185 @panic ESTART_6 Error_Code; If initialization of local properties to default fails.
  2186 				Error_Code is the error code returned by UserSvr::LocalePropertiesSetDefaults().
  2187 @panic ESTART_1 -1; If unable to create domain manager.
  2188 @panic ESTART_2 Error_Code; If initialization of domain manager fails.
  2189 				Error_Code is the error code returned by RDmDomainManager::WaitForInitialization().
  2190 */
  2191 TInt TFSStartup::Run()
  2192 	{
  2193 
  2194 	TInt r = UserSvr::LocalePropertiesSetDefaults();
  2195 	__ASSERT_ALWAYS(r==KErrNone,Panic(ELitLocaleInitialisationFail,r));
  2196 
  2197 	LocalDriveInit();				
  2198 
  2199 #ifdef AUTO_PROFILE
  2200 	StartProfiler();
  2201 #endif
  2202 	InitialiseHAL();
  2203 
  2204 	
  2205 	r=LoadCodePageDll();
  2206 	if(r != KErrNone)
  2207 	{
  2208 	DEBUGPRINT1("\nLoadCodePageDll() FAILED !!! : returned : %d", r);
  2209 	}
  2210 
  2211     // Seperate ScanDrive from MountDrive; this allows drives to be mounted
  2212     // followed by locale loading. Scanning drives after locale is set thus can
  2213     // recognise non-english filename.
  2214     MountRemovableDrives();
  2215 
  2216 #ifdef _DEBUG
  2217 	// display the setting for all drives
  2218 	DEBUGPRINT("   L  FSY      OBJ      EXT      Flags    FileCacheFlags");
  2219     for(TInt i=0;i<KMaxLocalDrives;i++)
  2220 		{
  2221 		if (iDriveMappingInfo[i].iLocalDriveNumber != KDriveInvalid)
  2222 			{
  2223 			TPtrC fsyName;	
  2224 			fsyName.Set(iDriveMappingInfo[i].iFsInfo.iFsyName?iDriveMappingInfo[i].iFsInfo.iFsyName:_L(""));
  2225 			TPtrC objName;	
  2226 			objName.Set(iDriveMappingInfo[i].iFsInfo.iObjName?iDriveMappingInfo[i].iFsInfo.iObjName:_L(""));
  2227 			TPtrC extName;	
  2228 			extName.Set(iDriveMappingInfo[i].iFsInfo.iExtName?iDriveMappingInfo[i].iFsInfo.iExtName:_L(""));
  2229 
  2230 			// Get the TFileCacheFlags for this drive
  2231 			TVolumeInfo volInfo;
  2232 			volInfo.iFileCacheFlags = TFileCacheFlags(0xFFFFFFFF);
  2233 			r = iFs.Volume(volInfo, iDriveMappingInfo[i].iDriveNumber);
  2234 			DEBUGPRINT7("%c: %-2d %-8S %-8S %-8S %08X %08X", 
  2235 				(TInt) TChar(iDriveMappingInfo[i].iDriveNumber) + TChar('A'),
  2236 				iDriveMappingInfo[i].iLocalDriveNumber,
  2237 				&fsyName,
  2238 				&objName,
  2239 				&extName,
  2240 				iDriveMappingInfo[i].iFsInfo.iFlags,
  2241 				volInfo.iFileCacheFlags);
  2242 			}
  2243 		}
  2244 #endif
  2245 
  2246 #ifndef SYMBIAN_EXCLUDE_ESTART_DOMAIN_MANAGER
  2247 	TDriveList list;
  2248 	r=iFs.DriveList(list);
  2249 	
  2250 	// Create Domain Manager Process
  2251 	if (!CreateServer(list,KDmManagerFileNameLit))
  2252 		Panic(ELitNoDM, KErrNotFound);
  2253 
  2254 	// Wait until Domain Manager completes its intialization 
  2255 	r=RDmDomainManager::WaitForInitialization();
  2256 	__ASSERT_ALWAYS(r==KErrNone,Panic(ELitDMInitFail,r));
  2257 	// Now File Server can connect to Domain Manager
  2258 #endif
  2259 
  2260 	return(KErrNone);
  2261 	}
  2262 
  2263 /**
  2264 Close the file system startup class.
  2265 */
  2266 void TFSStartup::Close()
  2267 	{
  2268 	
  2269 	// Ensure that the file servers local drive mapping is set.
  2270 	if (iDriveSwapCount)
  2271 		SwapFServLocalDriveMapping(KDriveInvalid,KDriveInvalid);
  2272 	delete iMapFile;
  2273 	iFs.Close();
  2274 	}
  2275 
  2276 TInt StartSysAgt2()
  2277 	{
  2278     // SysAgt2Svr uid
  2279 	const TUid KSystemAgentExeUid = {0x10204FC5}; 
  2280 	const TUidType serverUid(KNullUid, KNullUid, KSystemAgentExeUid);
  2281 
  2282     RProcess server;
  2283 	TInt err = server.Create(KSystemAgentName, KNullDesC, serverUid);
  2284 	if(err != KErrNone)
  2285 		return err;
  2286 
  2287     TRequestStatus stat;
  2288 	server.Rendezvous(stat);
  2289 	if(stat != KRequestPending)
  2290 		server.Kill(0);		// abort startup
  2291 	else
  2292 		server.Resume();	// logon OK - start the server
  2293 	User::WaitForRequest(stat);		// wait for start or death
  2294 
  2295     // we can't use the 'exit reason' if the server panicked as this
  2296 	// is the panic 'reason' and may be '0' which cannot be distinguished
  2297 	// from KErrNone
  2298 	err = server.ExitType() == EExitPanic ? KErrGeneral : stat.Int();
  2299 	server.Close();
  2300 	return err;
  2301 	}
  2302 
  2303 /**
  2304 This function is intended to be derived by licensee to show format progress
  2305 in their way.
  2306 
  2307 @param aPercent Percentage of format process
  2308 @param aDrive	Drive number
  2309 */
  2310 void TFSStartup::ShowFormatProgress(TInt /*aPercent*/, TInt /*aDrive*/)
  2311     {
  2312     }
  2313 
  2314 
  2315 
  2316 /**
  2317 This function loads the codepage dll based on the language index.
  2318 
  2319 @return KErrNotFound  if No codepage dll is found to be loaded
  2320 		KErrNone 	  if codepage dll is successfully loaded
  2321 */
  2322 
  2323 _LIT(KNonStandardCodePageName, "X-FAT%u");
  2324 _LIT(KMicrosoftStandardCodePageName, "CP%u");
  2325 
  2326 TInt LoadCodePageDll()
  2327 	{
  2328     // Always MS codepage type. Currently only supports the Microsoft Standard codepage names
  2329     // cp932.dll, cp 950.dll etc
  2330     const TFatFilenameConversionType fatConvType = EFatConversionMicrosoftCodePage;
  2331     TInt fatConvNumber = 0;
  2332 
  2333     TInt err = KErrNone;
  2334 	TBuf<KMaxCodepageDllName> codepageDllName;
  2335 	TBool CodepageFound = EFalse;
  2336 
  2337 /*  Default LanguageID --> LocaleDll --> CodepageDll Mapping. Must be maintained.
  2338 	|---------------|---------------------------|-------------------------|---------------------------|
  2339 	| Language ID	|	Language Name			|	Locale dll (eloc.xxx) |	FATCharsetConv (cpnnn.dll)|
  2340 	|---------------|---------------------------|-------------------------|---------------------------|
  2341 	| 29			|	TaiwanChinese			|	elocl.29			  |	cp950.dll				  |
  2342 	| 30			|	HongKongChinese			|	elocl.30			  |	cp950.dll				  |
  2343 	| 31			|	PrcChinese				|	elocl.31			  |	cp936.dll				  |
  2344 	| 32			|	Japanese				|	elocl.32		 	  |	cp932.dll				  |
  2345 	| 157			|	English taiwan			|	elocl.157			  |	cp950.dll				  |
  2346 	| 158			|	English HK				|	elocl.158			  |	cp950.dll				  |
  2347 	| 159			|	English prc				|	elocl.159			  |	cp936.dll				  |
  2348 	| 160			|	English japan			|	elocl.160			  |	cp932.dll				  |
  2349 	| 326			|	Bahas Malay				|	elocl.326			  |	cp936.dll				  |
  2350 	| 327			|	Indonesian(APAC)(Bahasa)|	elocl.327			  |	cp936.dll				  |
  2351 	|---------------|---------------------------|-------------------------|---------------------------|
  2352 	
  2353 	Language ID	is read from the HAL data file as Language Index. Based on the read Language Index, 
  2354 	corresponding Codepage Dll name is created.
  2355 */
  2356 
  2357 	TInt languageIndex;
  2358 	TInt error=HAL::Get(HALData::ELanguageIndex,languageIndex);
  2359 	if (error==KErrNone)
  2360 		{
  2361 		switch(languageIndex)
  2362 			{
  2363 			case 29:
  2364 				{
  2365 				fatConvNumber = 950;
  2366 				CodepageFound=ETrue;
  2367 				break;
  2368 				}
  2369 			case 30:
  2370 				{
  2371 				fatConvNumber = 950;
  2372 				CodepageFound=ETrue;
  2373 				break;
  2374 				}
  2375 			case 31:
  2376 				{
  2377 				fatConvNumber = 936;
  2378 				CodepageFound=ETrue;
  2379 				break;
  2380 				}
  2381 			case 32:
  2382 				{
  2383 				fatConvNumber = 936;
  2384 				CodepageFound=ETrue;
  2385 				break;
  2386 				}
  2387 			case 157:
  2388 				{
  2389 				fatConvNumber = 950;
  2390 				CodepageFound=ETrue;
  2391 				break;
  2392 				}
  2393 			case 158:
  2394 				{
  2395 				fatConvNumber = 950;
  2396 				CodepageFound=ETrue;
  2397 				break;
  2398 				}
  2399 			case 159:
  2400 				{
  2401 				fatConvNumber = 936;
  2402 				CodepageFound=ETrue;
  2403 				break;
  2404 				}
  2405 			case 160:
  2406 				{
  2407 				fatConvNumber = 932;
  2408 				CodepageFound=ETrue;
  2409 				break;
  2410 				}
  2411 			case 326:
  2412 				{
  2413 				fatConvNumber = 936;
  2414 				CodepageFound=ETrue;
  2415 				break;
  2416 				}
  2417 			case 327:
  2418 				{
  2419 				fatConvNumber = 936;
  2420 				CodepageFound=ETrue;
  2421 				break;
  2422 				}
  2423 			default:
  2424 				{
  2425 				CodepageFound=EFalse;
  2426 				break;
  2427 				}
  2428 			}
  2429 		}
  2430 
  2431 	// Do not use any codepage dll if the language index uses default FATCharsetconv conversions.
  2432 	if(!CodepageFound)
  2433 		return KErrNotFound;
  2434 
  2435 	// Create the codepage dll name to be loaded.
  2436 	switch(fatConvType)
  2437 		{
  2438 		// coverity[dead_error_condition]
  2439 		// Always MS codepage type. Currently only supports the Microsoft Standard codepage names.
  2440 		case EFatConversionDefault:
  2441 			// Undefined conversion scheme; conversion obtained is whatever the
  2442 			// default policy is for this version of the OS.
  2443 			DEBUGPRINT("...EFatConversionDefault");
  2444 			break;
  2445 		case EFatConversionNonStandard:
  2446 			// x-fat<nnn>.dll is loaded, where <nnn> is the FAT filename conversion number.
  2447 			DEBUGPRINT("...EFatConversionNonStandard");
  2448 			codepageDllName.Format(KNonStandardCodePageName, fatConvNumber);
  2449 			break;
  2450 		case EFatConversionMicrosoftCodePage:
  2451 			// cp<nnn>.dll is loaded, where <nnn> is the FAT filename conversion number.
  2452 			DEBUGPRINT("...EFatConversionMicrosoftCodePage");
  2453 			codepageDllName.Format(KMicrosoftStandardCodePageName, fatConvNumber);
  2454 			break;
  2455 		default:
  2456 			DEBUGPRINT("...FAT Conversion Type Unknown");
  2457 			break;
  2458 		}
  2459 
  2460 	// Load the codepage dll.
  2461 	if(codepageDllName.Length())
  2462 		{
  2463 		// No need for an F32 API to do this - ESTART is then only intended client for now.
  2464 		//  - Note that we load the code page via the loader, as doing so in the file server
  2465 		//	  will cause deadlock (as RLibrary::Load depends on the file server).
  2466 		RLoader loader;
  2467 		err = loader.Connect();
  2468 		if (err==KErrNone)
  2469 			{
  2470 			err = loader.SendReceive(ELoadCodePage, TIpcArgs(0, &codepageDllName, 0));
  2471 			loader.Close();
  2472 			}
  2473 		DEBUGPRINT2("...Loaded codepage DLL : %S [err: %d]", &codepageDllName, err);
  2474 		}
  2475 
  2476 	return(err);
  2477 	}
  2478