sysstatemgmt/systemstarter/src/resourcefilereader2.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstarter/src/resourcefilereader2.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,448 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <barsread.h>
+#include <e32uid.h>
+#include <e32modes.h>
+#include <startup.hrh>
+#include <hal.h>
+#include <hal_data.h>
+#include <startupproperties.h>
+#include "resourcefilereader2.h"
+#include "SystemStartupStateInfo.h"
+#include "StartupCommand.h"
+#include "startuputilprovider.h"
+#include "BootModeMapping.h"
+#include "appstarter2.h"
+#include "DllStarter.h"
+#include "StartupSplashScreen.h"
+#include "initapparcserver2.h"
+#include "SystemStartupDllInfo.h"
+#include "multiplewait2.h"
+#include "amastarter.h"
+
+#include "SysStartDebug.h"
+#include "sysstartpanic.h"
+
+const TUint KEntryPointIndex = 1;
+
+/** Read splash screen information from the resource file and return an object
+that can start/kill it
+*/
+MStartupCommand* CResourceFileReader::ReadSplashScreenL(TResourceReader& aReader)
+	{
+	TBool kill = static_cast<TUint16>(aReader.ReadUint16());
+	HBufC* path = aReader.ReadTPtrC().AllocLC();
+	CStartupSplashScreen* command = CStartupSplashScreen::NewL(!kill, path);
+	CleanupStack::Pop(path);	// "command" takes ownership of path
+	return command;
+	}
+		
+/** Read app arc server initialisation information from the resource file
+and return an object that can start it
+*/
+MStartupCommand* CResourceFileReader::ReadAppArcInitL()
+	{
+	return CInitAppArcServer::NewL(*iStartupUtilProvider);
+	}
+
+/** Read in the fields of the MULTIPLE_WAIT command in the SSC. 
+Create a CMultipleWait object containing the list of deferred commands encountered
+since the last MULTIPLE_WAIT command.   
+*/ 
+MStartupCommand* CResourceFileReader::ReadMultipleWaitInfoL(TResourceReader& aReader, CommandList& aDeferredList)
+	{
+	// Read values from the SSC
+	TInt timeout = aReader.ReadInt32();
+	TInt fail = static_cast<TUint16>(aReader.ReadUint16());
+	
+	// Create a CMultipleWait object to hold the data to be used during 
+	// the command execution.
+	CMultipleWait* waitCommand = CMultipleWait::NewL(aDeferredList, *iStartupUtilProvider);
+	
+	// Populate the command with the values just read from the SSC.
+	waitCommand->SetTimeout(timeout);
+	
+	// Check that the fail_on_error value is valid.	
+	if ((fail != EIgnoreCommandFailure) && (fail != EPanicOnCommandFailure))   
+		{	
+		DEBUGPRINT2(_L("SysStart: Invalid fail_on_error value of %d"), fail);
+		PanicNow(KPanicResourceFileReader, EInvalidMultipleWaitFailOnError);
+		} 
+	waitCommand->SetFailOnError(fail);
+	 	
+ 	return waitCommand; 
+	}
+	
+/**
+*/
+MStartupCommand* CResourceFileReader::ReadAmaInfoL(TResourceReader& aReader)
+	{
+	TUid id = TUid::Uid(aReader.ReadUint32());
+
+	CAmaStarter *command = CAmaStarter::NewL(id);
+	
+	return command;	
+	}
+	
+/** Read DLL information from the resource file and store in an object to be 
+used during dll function invocation
+*/
+MStartupCommand* CResourceFileReader::ReadDllInfoL(TResourceReader& aReader)
+{ 
+	// Read the main START_DLL_INFO fields from the SSC (static start-up 
+	// configuration) file.
+	TPtrC dllName = aReader.ReadTPtrC();
+	TUint8 ordinal = aReader.ReadUint8();
+ 	TInt fail = static_cast<TBool>(aReader.ReadInt16());
+	TUint8 retries = static_cast<TUint8>(aReader.ReadUint8());
+
+	// Additional validation
+	if ((fail != EIgnoreCommandFailure) && (fail != EPanicOnCommandFailure))   
+		{	
+		DEBUGPRINT2(_L("SysStart: Invalid fail_on_error value of %d"), fail);
+		PanicNow(KPanicResourceFileReader, EInvalidDLLFailOnError);
+		}  
+ 
+ 	if (ordinal == 0)
+ 		{
+ 		DEBUGPRINT1(_L("Invalid ordinal value of 0"));
+		PanicNow(KPanicResourceFileReader, EInvalidOrdinal0);
+ 		}
+ 		
+	// Store the information to be used later during function invocation
+	CSystemStartupDllInfo* dllInfo = CSystemStartupDllInfo::NewLC();	
+	dllInfo->SetDllNameL(dllName); 
+	dllInfo->SetOrdinal( ordinal);  
+	dllInfo->SetFailOnError(fail);
+ 	dllInfo->SetNoOfRetries(retries); 
+  
+  	// Read the DLL custom data link from the START_DLL_INFO struct
+ 	TUint32 dllDataLink = aReader.ReadUint32();
+ 
+ 	// Validate data link value
+ 	if (dllDataLink == 0)
+ 		{
+ 		DEBUGPRINT1(_L("Invalid custom_dll_data_link value of 0"));
+		PanicNow(KPanicResourceFileReader, EInvalidDataLink0);
+ 		}
+ 		
+ 	// Store the data found under the dllDataLink structure into a buffer
+ 	// for custom processing by licensee (See CDllStarter::Execute)
+  	dllInfo->SetDllBuffer(iResourceFile.AllocReadLC(dllDataLink));
+  		
+  	// The above read a resource into a heap descriptor and put a pointer 
+  	// to that descriptor onto the cleanup stack. Therefore this must now be 
+  	// popped off the stack.
+	CleanupStack::Pop();
+	
+	// Create a command using the DLL info retrieved.
+	CDllStarter* command = CDllStarter::NewL(dllInfo);
+		
+	// Pop dllInfo of the stack
+	CleanupStack::Pop(dllInfo);
+
+	return command;
+	}
+ 
+//
+// Standard Symbian factory functions/destructor
+//
+
+CResourceFileReader* CResourceFileReader::NewL(TInt aBootMode, RFs& aFs)
+	{
+	CResourceFileReader* self = CResourceFileReader::NewLC(aBootMode, aFs);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CResourceFileReader* CResourceFileReader::NewLC(TInt aBootMode , RFs& aFs)
+	{
+	TFileName resourceFile;
+	TBootModeMapping mapping;
+	
+	mapping.GetResourceFileName(aBootMode, resourceFile, aFs);
+	
+	DEBUGPRINT2(_L("SysStart: using resource file %S"), &resourceFile);
+
+	CResourceFileReader* self = new (ELeave) CResourceFileReader(aBootMode, aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL(resourceFile);
+	return self;
+	}
+
+CResourceFileReader::~CResourceFileReader()
+	{
+	iResourceFile.Close();
+	delete iStartupUtilProvider;	
+	}
+
+//
+// Public functions.
+//
+
+/** Gets information about the next start-up state. This involves reading the state information
+and constructing the command list for this state.
+*/
+MStartupStateInfo* CResourceFileReader::GetStateInfoL()
+	{
+	return ((iState < NULL) ? NULL : ReadStateInformationL());
+	}
+
+
+//
+// Private functions
+//
+
+CResourceFileReader::CResourceFileReader(TInt aBootMode, RFs& aFs)
+	: iFs(aFs), iBootMode(aBootMode)
+	{
+	iMaxStartupMode = -1;
+	}
+
+void CResourceFileReader::ConstructL(const TDesC& aResourceFile)
+	{
+    iResourceFile.OpenL(iFs, aResourceFile);
+    iStartupUtilProvider = CStartupUtilProvider::NewL();    
+	}
+ 
+void CResourceFileReader::FindFirstStateEntryL()
+	{
+	HBufC8* dataBuffer = iResourceFile.AllocReadLC(KEntryPointIndex);
+	TResourceReader reader;
+	reader.SetBuffer(dataBuffer);
+	iState = reader.ReadInt32();
+	CleanupStack::PopAndDestroy(dataBuffer);
+	}
+
+/** Read state information from the resource file
+*/
+CSystemStartupStateInfo* CResourceFileReader::ReadStateInformationL()
+	{
+	if (iState == 0)
+		{
+		FindFirstStateEntryL();
+		}
+		
+	CSystemStartupStateInfo* stateInfo = CSystemStartupStateInfo::NewLC();
+
+	HBufC8* dataBuffer = iResourceFile.AllocReadLC(iState);
+	TResourceReader reader;
+	reader.SetBuffer(dataBuffer);
+
+	TUint8 id = reader.ReadUint8();
+	
+	// Validate state id field. State id can be any int except for the 
+	// currently reserved values.
+	if ((id == EReservedStartUpState1) || (id == EReservedStartUpState2) ||
+	    (id == EReservedStartUpState4) || (id == EReservedStartUpState5)) 
+		{
+ 		DEBUGPRINT2(_L("Invalid state id of %d"), id);
+		PanicNow(KPanicResourceFileReader, EInvalidStateId);
+		}  	
+
+	// Store the state id value.
+	stateInfo->SetStateId(id);
+
+	TPtrC stateName = reader.ReadTPtrC();
+	stateInfo->SetName(stateName);
+
+	TUint32 commandListId = reader.ReadUint32();
+	
+    iState = reader.ReadInt32();	// Link to next state.
+ 
+ 	// The retries field specifies how many times to re-attempt 
+ 	// state transition in the case of failure
+	TNoOfRetries noOfRetries = static_cast<TNoOfRetries>(reader.ReadUint16()); 
+
+	// Validate field and store
+	if ((noOfRetries != ERetry0) && (noOfRetries != ERetry1))
+		{
+ 		DEBUGPRINT2(_L("Invalid no_of_retries_on_failure value of %d"), noOfRetries);
+		PanicNow(KPanicResourceFileReader, EInvalidNoOfRetries);
+		}  
+	stateInfo->SetNoOfRetries(noOfRetries);
+	 
+	// The next field specifies what should be done on a state transition 
+	// failure - ignore or panic  
+	TActionOnStateTransitionFailure actionOnStateTransitionFailure = 
+	        static_cast<TActionOnStateTransitionFailure>(reader.ReadUint16());  
+
+	// Validate field and store.
+	if ((actionOnStateTransitionFailure != EIgnoreFailure) && (actionOnStateTransitionFailure != EPanicOnFailure))
+		{
+ 		DEBUGPRINT2(_L("Invalid action_on_failure value of %d"), actionOnStateTransitionFailure);
+		PanicNow(KPanicResourceFileReader, EInvalidActionOnFailure);
+		}  
+	stateInfo->SetActionOnStateTransitionFailure(actionOnStateTransitionFailure);
+    
+    CleanupStack::PopAndDestroy(dataBuffer);
+
+    if (iState == 0)
+    	{
+    	// Just read the last state info - make sure that we don't try to
+    	// read any more.
+    	iState = -1;
+    	}
+     
+ 	CommandList commandList = ReadCommandListL(commandListId);
+	stateInfo->SetCommandList(commandList);
+	CleanupStack::Pop(stateInfo);
+
+    return stateInfo;
+	}
+	
+/** Read the command list from the resource file
+*/
+CommandList CResourceFileReader::ReadCommandListL(TUint32 aCommandListId)
+	{
+	CommandList commandList; 
+	
+	// Some of the commands will be deferred apps or processes (i.e. it is not 
+	// checked that they have completed until a MULTIPLE_WAIT command is issued). 
+	// Create a list of these commands so they can be referred to from a 
+	// CMultipleWait object.
+	CommandList deferredList;
+		
+	HBufC8* dataBuffer = iResourceFile.AllocReadLC(aCommandListId);
+	TResourceReader reader;
+	reader.SetBuffer(dataBuffer);
+
+	TUint16 commandListCount = reader.ReadUint16();
+
+	for(TUint i = 0; i < commandListCount; ++i)
+		{
+		const TStartupCommandType type = static_cast<TStartupCommandType>(reader.ReadUint16());	
+		MStartupCommand* command = NULL;
+		switch (type)
+			{
+		case EStartupApp:					
+		case EStartupProcess:
+		case EStartupApp2:					
+		case EStartupProcess2:			
+			{
+			reader.Rewind(sizeof(TUint16)); //CStartupProperties need to read the struct from start
+			CStartupProperties* appInfo = CStartupProperties::NewLC(reader);
+			if (appInfo->RecoveryMethod() == ERestartOSWithMode)
+				{
+				ValidateRestartMode(appInfo->RestartMode());
+				}
+			command = CAppStarter::NewL(appInfo, *iStartupUtilProvider);
+			CleanupStack::Pop(appInfo); // ownership passed above
+			CleanupStack::PushL(command);
+			 
+			// If the command has a start_method of EDeferredWaitForStart
+			// in the SSC then it needs to be added to the current deferred
+			// list. This will be passed to a CMultipleWait object once a 
+			// MULTIPLE_WAIT command is encountered.
+			if (command && (appInfo->StartMethod() == EDeferredWaitForStart))
+				{  
+				User::LeaveIfError(deferredList.Append(command)); 				
+				}
+			break;
+			}
+ 		
+		case EStartupSplashScreen:
+			command = ReadSplashScreenL(reader);
+			CleanupStack::PushL(command);
+			break;
+
+		case EInitAppArcServer:
+			command = ReadAppArcInitL();
+			CleanupStack::PushL(command);
+			break;
+
+		case EStartupDLL:
+			command = ReadDllInfoL(reader);
+			CleanupStack::PushL(command);
+			break;
+			
+		case EMultipleWait:
+		
+			// A MULTIPLE_WAIT command should only be provisioned in the SSC
+			// if there are preceeding deferred commands.
+			if (deferredList.Count() == 0)
+				{		
+		 		DEBUGPRINT1(_L("SysStart: Resource File Reader extra multiple wait command in SSC"));
+				PanicNow(KPanicResourceFileReader, EExtraMultipleWaitCommand);
+				}
+			// A list has been built up of any processes/apps with a start_method of
+			// EDeferredWaitForStart. Pass this list as parameter so that a 
+			// CMultipleWait object can be created which has access to this list.			  
+			command = ReadMultipleWaitInfoL(reader, deferredList);
+			CleanupStack::PushL(command);
+			
+			// As processing continues more deferred command may be encountered
+			// along with a subsequent MULTIPLE_WAIT struct. Reset the deferred list
+			// so that the next set of deferred commands can be stored.
+			deferredList.Reset();   
+			break;
+			
+		case EStartupAMAStarter:
+			command = ReadAmaInfoL(reader);
+			CleanupStack::PushL(command);
+			break;
+		
+		default:
+	 		DEBUGPRINT2(_L("SysStart: Resource File Reader unknown command type %d"), type);
+			PanicNow(KPanicResourceFileReader, EInvalidCommandType);
+			break;
+			}
+			
+		if (command)
+			{
+			User::LeaveIfError(commandList.Append(command));
+			CleanupStack::Pop(command);
+			}
+		}
+	
+	// Any deferred commands must be followed by a MULTIPLE_WAIT command within
+	// the same state. Therefore at this stage all commands in the state have been 
+	// processed so the deferred list should be empty.
+	
+	if (deferredList.Count() != 0)
+		{		
+		PanicNow(KPanicResourceFileReader, EMissingMultipleWaitCommand);
+		}
+
+	deferredList.Reset();	
+    CleanupStack::PopAndDestroy(dataBuffer);
+	return commandList;
+	}
+
+void CResourceFileReader::ValidateRestartMode(TInt aStartupMode)
+	{
+#ifndef __WINSCW__ // HAL::Get(EMaximumRestartStartupModes...) is only supported in H4	
+	// check that the startup mode is valid, first retrieve max startup mode if not retrieved yet
+	if (iMaxStartupMode == -1)
+		{
+		TInt err = HAL::Get(HALData::EMaximumRestartStartupModes, iMaxStartupMode);
+		if (err != KErrNone)
+			{
+	 		DEBUGPRINT2(_L("SysStart: Failed to get max startup mode err = %d"), err);
+			PanicNow(KPanicResourceFileReader, EMissingMaxStartupMode);
+			}
+		DEBUGPRINT2(_L("SysStart: HAL max startup mode = %d"), iMaxStartupMode);
+		}
+
+	if (aStartupMode > iMaxStartupMode)
+		{
+ 		DEBUGPRINT2(_L("SysStart: Invalid failure_recovery_startup_mode %d"), aStartupMode);
+		PanicNow(KPanicResourceFileReader, EInvalidStartupMode);
+		}
+#else
+	(void)aStartupMode;
+#endif
+	}