--- /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
+ }