sysstatemgmt/systemstateplugins/gsapolicy/src/gsastatepolicystartup.cpp
changeset 0 4e1aa6a622a0
child 70 653a8b91b95e
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2007-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 "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 //
       
    15 
       
    16 #include <barsc2.h>
       
    17 #include <barsread2.h>
       
    18 #include <e32property.h>
       
    19 #include <e32uid.h>
       
    20 #include <e32std.h>
       
    21 #include <bautils.h>
       
    22 
       
    23 #include <ssm/ssmcmd.hrh>
       
    24 #include <ssm/ssmsubstates.hrh>
       
    25 #ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
       
    26 #include <ssm/ssmpatchableconstants.h>
       
    27 #include <ssm/conditiontypes.hrh>
       
    28 #endif
       
    29 
       
    30 #include <ssm/ssmstatetransition.h>
       
    31 #include <ssm/ssmcommandlistresourcereader.h>
       
    32 #include <ssm/ssmmaxbootattempts_patch.h>
       
    33 
       
    34 #include "gsastatepolicystartup.h"
       
    35 #include "ssmdebug.h"
       
    36 #include "ssmpanic.h" 
       
    37 #include "s32file.h" 
       
    38 
       
    39 _LIT(KBootUpFile, ":\\private\\2000d75b\\bootupinfo\\bootupcount.bin");
       
    40 
       
    41 /**
       
    42  Attempt to reboot the device (forever) on boot failure. Used when KSsmMaxBootAttempts is set to '0xFFFFFFFF'.
       
    43 */
       
    44 const TInt KSsmAttemptRebootForever = 0xFFFFFFFF;
       
    45 
       
    46 /**
       
    47 Panic used by Startup policy plug-in when resource reader is invalid.
       
    48 Strings must not be longer than 16 characters or they will be truncated by User::Panic()
       
    49 */
       
    50 _LIT(KPanicGsaStartupState, "StartupPolicy");
       
    51 
       
    52 /**
       
    53  Start-up state policy resource file path format : "z:/private/<SID of SSM>/startup/<Value of KSystemStartupModeKey>/"
       
    54 */
       
    55 _LIT(KCommandListPath, "z:\\private\\2000D75B\\startup\\%d\\");
       
    56 
       
    57 /**
       
    58  Commandlist path to launch 'sysstart.exe' when a resource file for 'start-up' is not found.
       
    59  fallback to 'sysstart.exe' resource file path format : "z:/private/<SID of SSM>/startup/fallback/"
       
    60 */
       
    61 _LIT(KFallbackCmdListPath, "z:\\private\\2000D75B\\startup\\fallback\\");
       
    62 
       
    63 /**
       
    64 Used to create an instance of MSsmStatePolicy class.
       
    65 
       
    66 @return A pointer to an instance of MSsmStatePolicy
       
    67 */
       
    68 EXPORT_C MSsmStatePolicy* CGsaStatePolicyStartup::NewL()
       
    69 	{
       
    70 	CGsaStatePolicyStartup* self = new (ELeave) CGsaStatePolicyStartup;
       
    71 	CleanupStack::PushL(self);
       
    72 	self->ConstructL();
       
    73 	CleanupStack::Pop(self);
       
    74 	return self;
       
    75 	}
       
    76 
       
    77 /**
       
    78 Gets the hardware reason for KSystemStartupModeKey and makes a RFs connection.
       
    79 Creates Command list path and the resource reader for startup.
       
    80 
       
    81 @leave One of the error value returned by 
       
    82 	    RProperty::Get() 
       
    83 	    RFs::Connect() 
       
    84 	    RArray::AppendL() 
       
    85 	    NewL()
       
    86 @see RProperty::Get
       
    87 */
       
    88 void CGsaStatePolicyStartup::ConstructL()
       
    89 	{
       
    90 	// Read the hardware reason
       
    91 	User::LeaveIfError(RProperty::Get(KUidSystemCategory, KSystemStartupModeKey, iHardwareReason));
       
    92 	User::LeaveIfError(iFs.Connect());
       
    93 	
       
    94 	// Add supported transitions from Startup 'ESsmStartup'
       
    95 	iCurrentlySupportedTransitions.AppendL(TSsmState(ESsmFail, KSsmAnySubState));
       
    96 	iCurrentlySupportedTransitions.AppendL(TSsmState(ESsmShutdown, KSsmAnySubState));
       
    97 	iCurrentlySupportedTransitions.AppendL(TSsmState(ESsmShutdown, ESsmShutdownSubStateCritical));
       
    98 
       
    99 	TFileName cmdListPath;
       
   100 	GetCommandListPath(iHardwareReason, cmdListPath);
       
   101 	DEBUGPRINT2(_L("Startup Policy : Startup command list path : %S"), &cmdListPath);
       
   102 
       
   103 	// create resource reader
       
   104 	iCommandListResourceReader = CSsmCommandListResourceReader::NewL(iFs, cmdListPath, *this);	
       
   105 	}
       
   106 
       
   107 /**
       
   108 default CTOR
       
   109 */
       
   110 CGsaStatePolicyStartup::CGsaStatePolicyStartup()
       
   111 	{
       
   112 	}
       
   113 
       
   114 /**
       
   115 DTOR
       
   116 */
       
   117 CGsaStatePolicyStartup::~CGsaStatePolicyStartup()
       
   118 	{
       
   119 	delete iCommandListResourceReader;
       
   120 	iSubStates.Close();
       
   121 	iFs.Close();
       
   122 	iCurrentlySupportedTransitions.Close();
       
   123 	}
       
   124 
       
   125 /**
       
   126 Initializes command list resource reader.
       
   127 
       
   128 @param aStatus to complete when the initialization operation has finished
       
   129 @panic EInvalidResourceReader if the command list resource reader is invalid
       
   130 
       
   131 @see MSsmStatePolicy::Initialize
       
   132 */
       
   133 void CGsaStatePolicyStartup::Initialize(TRequestStatus& aStatus)
       
   134 	{
       
   135 	__ASSERT_DEBUG(iCommandListResourceReader, PanicNow(KPanicGsaStartupState, EInvalidResourceReader));
       
   136 	
       
   137 	// initialise command list resource reader.
       
   138 	iCommandListResourceReader->Initialise(aStatus);
       
   139 	}
       
   140 
       
   141 /**
       
   142 Cancels an asynchronous Initialize operation.
       
   143 
       
   144 @see MSsmStatePolicy::InitializeCancel
       
   145 */
       
   146 void CGsaStatePolicyStartup::InitializeCancel()
       
   147 	{
       
   148 	iCommandListResourceReader->InitialiseCancel();
       
   149 	}
       
   150 
       
   151 /** 
       
   152 Deletes all resources and frees itself.
       
   153 
       
   154 @see MSsmStatePolicy::Release
       
   155 */
       
   156 void CGsaStatePolicyStartup::Release()
       
   157 	{
       
   158 	delete this;
       
   159 	}
       
   160 
       
   161 /** 
       
   162 Determines if an incoming startup state transition request should be accepted or rejected.
       
   163 Clients calling this API should posess 'ECapabilityPowerMgmt', else the API will return ENotAllowed.
       
   164 
       
   165 @param aRequest Contains information about the new request
       
   166 @param aCurrent Contains NULL or the first accepted but not yet completed transition request
       
   167 @param aQueued Contains NULL or a second accepted but not yet started transition request
       
   168 @param aMessage Message sent by SSM server, used to check if the client has 'ECapabilityPowerMgmt'
       
   169 
       
   170 @return one of the TResponse value
       
   171 @see MSsmStatePolicy::TransitionAllowed
       
   172 @see MSsmStatePolicy::TResponse
       
   173 */
       
   174 MSsmStatePolicy::TResponse CGsaStatePolicyStartup::TransitionAllowed(const TSsmStateTransition& aRequest, TSsmStateTransition const* aCurrent, 
       
   175 																TSsmStateTransition const* aQueued, const RMessagePtr2& aMessage)
       
   176 	{
       
   177 	TResponse response = ENotAllowed;
       
   178 	if (!aMessage.HasCapability(ECapabilityPowerMgmt))
       
   179 		{
       
   180 		DEBUGPRINT1(_L ("Startup Policy : Capability Check Failed."));
       
   181 		return response;
       
   182 		}
       
   183 
       
   184 	//Check if the requested transition is supported from current state
       
   185 	if(TransitionSupported(aRequest.State()))
       
   186 		{
       
   187 		if((NULL == aCurrent) && (NULL == aQueued))
       
   188 			{
       
   189 			// SsmServer is idle
       
   190 			response = EDefinitelyAllowed;
       
   191 			}
       
   192 		else if((aRequest.State().MainState() == ESsmFail) || (aRequest.State().MainState() == ESsmShutdown))
       
   193 			{
       
   194 			// Going into failed state or shutdown state will override anything currently ongoing or queued
       
   195 			response = EReplaceCurrentClearQueue;
       
   196 			}
       
   197 		}
       
   198 
       
   199 #ifdef _DEBUG
       
   200 	TSsmStateName name = aRequest.State().Name();
       
   201 	if(ENotAllowed == response)
       
   202 		{
       
   203 		DEBUGPRINT3(_L("Startup Policy : Transition (Requested State: %S) is not allowed (Response: %d)."), &name, response);
       
   204 		}
       
   205 	else
       
   206 		{
       
   207 		DEBUGPRINT3(_L("Startup Policy : Transition (Requested State %S) is allowed (Response %d)."), &name, response);		
       
   208 		}
       
   209 #endif
       
   210 	return response;
       
   211 	}
       
   212 
       
   213 /** 
       
   214 Create the command list associated with a sub state transition.
       
   215 
       
   216 @param aState Contains the state and substate that identifies the command list to create
       
   217 @param aReason Contains the reason as given by the request
       
   218 @param aStatus to complete when the operation has finished
       
   219 @panic EInvalidResourceReader if the command list resource reader is invalid
       
   220 @see MSsmStatePolicy::PrepareCommandList
       
   221 */ 
       
   222 void CGsaStatePolicyStartup::PrepareCommandList(TSsmState aState, TInt aReason, TRequestStatus& aStatus)
       
   223 	{
       
   224 	__ASSERT_DEBUG(iCommandListResourceReader, PanicNow(KPanicGsaStartupState, EInvalidResourceReader));
       
   225 
       
   226 	iSoftwareReason = aReason;
       
   227 
       
   228 	//Let's start from the beginning if no specific minor state is selected
       
   229 	iRequestedSubState = ((aState.SubState() == KSsmAnySubState) ? ESsmStartupSubStateCriticalStatic : aState.SubState());
       
   230 	TSsmState publishState;
       
   231 	publishState.Set(aState.MainState(), iRequestedSubState);
       
   232 
       
   233 	const TInt commandListId = publishState.SubState();
       
   234 
       
   235 	//Build the commandlist from resource
       
   236 	iCommandListResourceReader->PrepareCommandList(commandListId, publishState, aStatus);
       
   237 	} //lint !e1746 Suppress parameter 'aState' could be made const reference
       
   238 
       
   239 /**
       
   240 Cancels asynchronous PrepareCommandList operation.
       
   241 
       
   242 @see MSsmStatePolicy::PrepareCommandListCancel
       
   243 */
       
   244 void CGsaStatePolicyStartup::PrepareCommandListCancel()
       
   245 	{
       
   246 	iCommandListResourceReader->PrepareCommandListCancel();
       
   247 	}
       
   248 
       
   249 /**	
       
   250 Return the command list once the  PrepareCommandList has completed.
       
   251 Ownership of the returned command list is transferred to the caller.
       
   252 @panic EInvalidResourceReader if the command list resource reader is invalid
       
   253 @return The command list created during the preceding PrepareCommandList step
       
   254 */
       
   255 CSsmCommandList* CGsaStatePolicyStartup::CommandList()
       
   256 	{
       
   257 	__ASSERT_DEBUG(iCommandListResourceReader , PanicNow(KPanicGsaStartupState, EInvalidResourceReader));
       
   258 
       
   259 	return iCommandListResourceReader->GetCommandList();
       
   260 	}
       
   261 
       
   262 /**
       
   263 Determines the next sub state transition.
       
   264 @param aCurrentTransition Contains the last executed state
       
   265 @param aReason Contains the reason as given by the request
       
   266 @param aError Contains the completion code from the last executed sub-state transition
       
   267 @param aSeverity Contains the severity of the failed command in case the sub-state transition ended with an error
       
   268 @param aNextState The next System State to head for, if there is one
       
   269 @panic EInvalidStartupstate if the current state is not startup
       
   270 @return 	ETrue if aNextState contains another System State to head for, or 
       
   271 		EFalse if there is no further transitions to do.
       
   272 @see MSsmStatePolicy::GetNextState
       
   273 */
       
   274 TBool CGsaStatePolicyStartup::GetNextState(TSsmState aCurrentTransition, TInt /*aReason*/, TInt aError, TInt /*aSeverity*/, TSsmState& aNextState)
       
   275 	{
       
   276 	__ASSERT_ALWAYS(aCurrentTransition.MainState() == ESsmStartup, PanicNow(KPanicGsaStartupState, EInvalidStartupState));
       
   277 
       
   278 	if (KErrNone != aError)	// Handle CLE error here
       
   279 		{
       
   280 		if (iLaunchSysStart)	// 'sysstart.exe' was launched unsuccessfully so launch 'sysagt2srv.exe' and 'wserv.exe'
       
   281 			{
       
   282 			iLaunchSysStart = EFalse;
       
   283 			iLaunchSysAgt2SrvAndWServ = ETrue;
       
   284 			DEBUGPRINT2(_L("Startup Policy : sysstart.exe launched with error : %d"), aError);
       
   285 			aNextState = TSsmState(ESsmStartup, ESsmStartupSubStateCriticalDynamic);
       
   286 			return ETrue;
       
   287 			}
       
   288 
       
   289 #ifdef __WINS__	// on emulator
       
   290 			{
       
   291 			DEBUGPRINT2(_L("Startup Policy : CLE returned with (error : %d), Panic on Emulator"), aError);
       
   292 			DEBUGPRINT1(_L("Startup Policy : Emulator (__WINS__) does not support a re-start, so Fail Policy is not invoked."));
       
   293 			PanicNow(KPanicGsaStartupState, EEmulatorPowerOff);
       
   294 			}
       
   295 #else	// on hardware/device
       
   296 			{
       
   297 			aNextState = TSsmState(ESsmFail, ESsmFailSubStateRestart);
       
   298 			if (KSsmAttemptRebootForever != KSsmMaxBootAttempts)
       
   299 				{
       
   300 				// Get number of boot attempts made till now from bootup log file
       
   301 				TInt bootCount = -1;
       
   302 				TRAPD(err, bootCount = GetBootupCountL());	// ignore failure and restart the device, we should get the value next time.
       
   303 				if (err!=KErrNone)
       
   304 					{
       
   305 					DEBUGPRINT2(_L("Startup Policy : GetBootupCountL() failed with (error: %d), error is deliberately ignored."), aError);
       
   306 					}
       
   307 				if (bootCount < KSsmMaxBootAttempts)
       
   308 					{
       
   309 					aNextState = TSsmState(ESsmFail, ESsmFailSubStateRestart);
       
   310 					}
       
   311 				else	// Maximum allowed boot attempts has been made. Device needs a poweroff. Probable candidate for a reset/reflash.
       
   312 					{
       
   313 					aNextState = TSsmState(ESsmFail, ESsmFailSubStatePowerOff);
       
   314 					}
       
   315 				}
       
   316 	#ifdef _DEBUG
       
   317 			TSsmStateName name = aNextState.Name();
       
   318 			DEBUGPRINT3(_L("Startup Policy : CLE returned with (error : %d) so moving to Fail State : %S."), aError, &name);
       
   319 	#endif
       
   320 			return ETrue;
       
   321 			}
       
   322 #endif
       
   323 		}
       
   324 	else if(iLaunchSysStart || iLaunchSysAgt2SrvAndWServ)	// If either sysstart or sysagt2srv and wserv was launched and CLE did not return an error
       
   325 		{
       
   326 		if (iLaunchSysStart)
       
   327 			{
       
   328 			iLaunchSysStart = EFalse;
       
   329 			DEBUGPRINT1(_L("Startup Policy : sysstart.exe launched successfully."));
       
   330 			}
       
   331 		if (iLaunchSysAgt2SrvAndWServ)
       
   332 			{
       
   333 			iLaunchSysAgt2SrvAndWServ = EFalse;
       
   334 			DEBUGPRINT1(_L("Startup Policy : sysagt2srv.exe and wserv.exe launched successfully."));
       
   335 			}
       
   336 		aNextState = TSsmState(ESsmNormal, KSsmAnySubState);	// move to Normal state
       
   337 		return ETrue;
       
   338 		}
       
   339 	else	// have to move one with the next substates in this state
       
   340 		{
       
   341 		// Get the sub states from resource reader only once
       
   342 		if (!iSubStatesCount)
       
   343 			{
       
   344 			// Get sub states list from resource reader
       
   345 			TRAPD(err, iCommandListResourceReader->GetCommandListIdsL(iSubStates));
       
   346 			if (err)
       
   347 				{
       
   348 				DEBUGPRINT2(_L("Startup Policy : Command list ids prepared with error: %d"), err);
       
   349 				}
       
   350 			else
       
   351 				{
       
   352 				iSubStatesCount = iSubStates.Count();
       
   353 				}
       
   354 			}
       
   355 
       
   356 		TInt index = iSubStates.Find(iRequestedSubState);
       
   357 
       
   358 		if (KErrNotFound == index)
       
   359 			{
       
   360 			DEBUGPRINT2(_L("Startup Policy : SubState for transition not found: %d"), index);
       
   361 			PanicNow(KPanicGsaStartupState, ESubStateIndexNotFound);
       
   362 			}
       
   363 		else if (index == (iSubStatesCount - 1))	// transition complete, move to Normal state
       
   364 			{
       
   365 			TInt retVal = EFalse;
       
   366 			// moving to next state as the transition is completed for ESsmStartup
       
   367 			if (iSubStatesCount && (iRequestedSubState == iSubStates[iSubStatesCount-1]))
       
   368 				{
       
   369 				aNextState = TSsmState(ESsmNormal, KSsmAnySubState);
       
   370 				retVal = ETrue;
       
   371 				}
       
   372 			return retVal;
       
   373 			}
       
   374 		else		// there is a substate available for transition, moved ahead
       
   375 			{
       
   376 			iRequestedSubState = iSubStates[++index];
       
   377 			aNextState = TSsmState(ESsmStartup, iRequestedSubState);
       
   378 #ifdef _DEBUG
       
   379 			TSsmStateName name = aNextState.Name();
       
   380 			DEBUGPRINT2(_L("Startup Policy : Transition to next state is : %S"), &name);
       
   381 #endif				
       
   382 			return ETrue;
       
   383 			}
       
   384 		}
       
   385 	return EFalse;
       
   386 	} //lint !e1746 Suppress parameter 'aCurrentTransition' could be made const reference
       
   387 
       
   388 /**
       
   389 Callback used by CSsmCommandListResourceReader when a decision needs to be made
       
   390 on whether to include a command in a command list or not.
       
   391 
       
   392 @param aResourceFile Instance of CResourceFile
       
   393 @param aResourceId Resource id of SSM_SYMBIAN_CONDITIONAL_INFORMATION struct for command
       
   394 @return ETrue in case the command needs to be included in command list, else EFalse.
       
   395 
       
   396 @see MSsmConditionalCallback::ConditionalCommandAllowedL
       
   397 */
       
   398 #ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN 
       
   399 TBool CGsaStatePolicyStartup::ConditionalCommandAllowedL(CResourceFile& aResourceFile, TInt aResourceId)
       
   400 #else
       
   401 TBool CGsaStatePolicyStartup::ConditionalCommandAllowedL(CResourceFile& /*aResourceFile*/, TInt /*aResourceId*/)
       
   402 #endif
       
   403 	{
       
   404 	TBool isAllowed = EFalse;        
       
   405 #ifdef SYMBIAN_SSM_GRACEFUL_SHUTDOWN
       
   406    	HBufC8* buf = aResourceFile.AllocReadLC(aResourceId);
       
   407    	TResourceReader reader; 
       
   408 	reader.SetBuffer(buf);
       
   409 	//Read the type of the command from the resource file
       
   410 	TUint16 type = reader.ReadUint16();
       
   411 	CleanupStack::PopAndDestroy(buf);
       
   412 	// check that the type is equal to "EGracefulShutdown"
       
   413 	if(type == EGracefulShutdown)    
       
   414 		{
       
   415 		//Check whether SSM graceful shutdown is enabled or not
       
   416 		if(IsSsmGracefulShutdown())   
       
   417 			{
       
   418 			isAllowed = ETrue;
       
   419 			}
       
   420 		}
       
   421 #else
       
   422 	// no commands use 'conditional_information' in Startup state command list.
       
   423 	PanicNow(KPanicGsaStartupState, EConditionalInfoNotImplemented);
       
   424 #endif
       
   425 	return isAllowed;
       
   426 	}
       
   427 
       
   428 /*
       
   429 Helper function to check whether requested transition is supported or not.
       
   430 */
       
   431 TBool CGsaStatePolicyStartup::TransitionSupported(const TSsmState& aRequestedState) const
       
   432 	{
       
   433 	return (iCurrentlySupportedTransitions.Find(aRequestedState) > KErrNotFound);
       
   434 	}
       
   435 
       
   436 /*
       
   437 Helper function to create command list path for start-up.
       
   438 Implements fallback mechanism to launch 'sysstart.exe' if static command list for 'start-up' state is not found.
       
   439 This temporary implementation is required during migration from existing 'sysstart' to 'ssma start-up'.
       
   440 */
       
   441 void CGsaStatePolicyStartup::GetCommandListPath(TUint aBootMode, TDes& aCmdListPath)
       
   442 	{
       
   443 	aCmdListPath.Format(KCommandListPath, aBootMode);
       
   444 	TBool found = BaflUtils::FolderExists(iFs, aCmdListPath);
       
   445 
       
   446 	// This Fallback mechanism is used internally during migration from 'sysstart' to 'ssma start-up' and is not required otherwise.
       
   447 	if (!found)
       
   448 		{
       
   449 		aCmdListPath.Copy(KFallbackCmdListPath());
       
   450 		iLaunchSysStart = ETrue;	// launch 'sysstart.exe'
       
   451 		}
       
   452 	}
       
   453 
       
   454 /*
       
   455 Helper function to get the boot count
       
   456 */
       
   457 TInt CGsaStatePolicyStartup::GetBootupCountL()
       
   458 	{
       
   459 	RBuf bootupInfoPath;
       
   460 	CleanupClosePushL(bootupInfoPath);
       
   461 	const TChar drive = RFs::GetSystemDriveChar();
       
   462 	TInt length = KBootUpFile().Length() + 1; /* for RFs::GetSystemDriveChar() */
       
   463 	bootupInfoPath.CreateL(length);
       
   464 	bootupInfoPath.Append(drive);
       
   465 	bootupInfoPath.Append(KBootUpFile());
       
   466 	TBool found = BaflUtils::FileExists(iFs, bootupInfoPath);
       
   467  	if(!found)
       
   468  		{
       
   469 		User::Leave(EBootupCountFileNotFound);
       
   470 		}
       
   471 
       
   472 	RFileReadStream file;
       
   473 	CleanupClosePushL(file);
       
   474 	User::LeaveIfError(file.Open(iFs, bootupInfoPath, EFileRead));
       
   475 	TInt bootCount = file.ReadUint8L();
       
   476 	CleanupStack::PopAndDestroy(&file);
       
   477 	CleanupStack::PopAndDestroy(&bootupInfoPath);
       
   478 	return bootCount;
       
   479 	}
       
   480