diff -r 000000000000 -r 4e1aa6a622a0 sysstatemgmt/systemstarter/src/resourcefilereader2.cpp --- /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 +#include +#include +#include +#include +#include +#include +#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(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(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(aReader.ReadInt16()); + TUint8 retries = static_cast(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(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(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(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 + }