os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/scmonitor.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/scmonitor.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1032 @@
     1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\debug\crashMonitor\src\scmonitor.cpp
    1.18 +// Core dump server - Kernel side crash monitor
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +/**
    1.23 + @file
    1.24 + @internalTechnology
    1.25 +*/
    1.26 +
    1.27 +#include <scmonitor.h>
    1.28 +#include <kernel/monitor.h>
    1.29 +#include <assp.h>
    1.30 +#include <drivers/crashflash.h>
    1.31 +#include <kernel/klib.h>
    1.32 +#include <crashlogwalker.h>
    1.33 +#include <scmconfigitem.h>
    1.34 +
    1.35 +#include "scmdatasave.h"
    1.36 +
    1.37 +GLDEF_D SCMonitor TheSCMonitor; //global definition of SCMonitor
    1.38 +
    1.39 +//keep things 4 byte aligned
    1.40 +const TInt KRestartType = SCMonitor::ESoftRestart;
    1.41 +
    1.42 +/**
    1.43 +SCMonitor constructor
    1.44 +*/
    1.45 +SCMonitor::SCMonitor()
    1.46 +	: iMultiCrashInfo(NULL)
    1.47 +	{
    1.48 +	}
    1.49 +
    1.50 +SCMonitor::~SCMonitor()
    1.51 +	{
    1.52 +	delete iMultiCrashInfo;
    1.53 +	}
    1.54 +
    1.55 +/**
    1.56 + Print data to the corresponding output channel. Derived from monitor
    1.57 + @param aDes the buffer containing the data
    1.58 + */
    1.59 +void SCMonitor::Print (const TDesC8& aDes )
    1.60 +	{
    1.61 +	//intended to do nothing
    1.62 +	}
    1.63 +
    1.64 +/**
    1.65 + * Allocates resources for SCMonitor
    1.66 + * cant fully construct in constructor as we are a kernel extension and resources are limited when we are created
    1.67 + */
    1.68 +void SCMonitor::StableConstruction()
    1.69 +	{
    1.70 +	LOG_CONTEXT
    1.71 +	iDataSave = new SCMDataSave(this, TheSCMonitor.iFlash);	
    1.72 +	
    1.73 +	//Configuration object for use upon crash
    1.74 +	iScmConfig = new SCMConfiguration();
    1.75 +	TInt err = iScmConfig->SetDefaultConfig();	
    1.76 +	if(KErrNone != err)
    1.77 +		{
    1.78 +		CLTRACE1("SCMonitor::StableConstruction - Unable to set default config err = %d", err);
    1.79 +		}
    1.80 +	
    1.81 +	
    1.82 +#ifdef NO_MULTICRASHINFO	
    1.83 +	iMultiCrashInfo = NULL;
    1.84 +#else	
    1.85 +
    1.86 +	//We need to take a look at the flash map from variant_norflash_layout.h
    1.87 +	iMultiCrashInfo = new SCMMultiCrashInfo();
    1.88 +
    1.89 +	TUint numberBlocks = KCrashLogSize / KCrashLogBlockSize;
    1.90 +	for(TUint32 cnt = 0; cnt < numberBlocks; cnt++)
    1.91 +		{
    1.92 +		iMultiCrashInfo->AddBlock(new SCMCrashBlockEntry(cnt, cnt * KCrashLogBlockSize, KCrashLogBlockSize));
    1.93 +		}
    1.94 +#endif
    1.95 +	}
    1.96 +
    1.97 +/**
    1.98 + * Start a secondary DFC queue for the Flash and Init the flash in the variant(h4)
    1.99 + * @param aAny
   1.100 + */
   1.101 +void StartSecondary (TAny* )
   1.102 +	{
   1.103 +	LOG_CONTEXT
   1.104 +	//InitFlash is implemented in the variant as it creates a variant
   1.105 +	//specific derived CrashFlash
   1.106 +	TheSCMonitor.InitFlash ( );
   1.107 +	TheSCMonitor.StableConstruction();
   1.108 +	}
   1.109 +
   1.110 +/**
   1.111 + * Global method to create a dfc queue
   1.112 + * @param Method to intialise the flash.
   1.113 + * @param Null
   1.114 + * @param Gets the address of the supervisor thread DFC queue
   1.115 + * @param TDfcQ priority number
   1.116 + * @return a DFC object
   1.117 + */
   1.118 +GLDEF_C TDfc StartSecondaryDfc(&StartSecondary, NULL, Kern::SvMsgQue(), KMaxDfcPriority-1);
   1.119 +
   1.120 +/**
   1.121 + * Kernel Main module entry - Own implementation( similar to crash logger)
   1.122 + * @param aReason reason to enter to the method
   1.123 + * @return One of the system wide codes
   1.124 + */
   1.125 +GLDEF_C TInt KernelModuleEntry(TInt aReason)
   1.126 +	{	
   1.127 +	if(aReason==KModuleEntryReasonVariantInit0)
   1.128 +		{
   1.129 +		new(&TheSCMonitor) SCMonitor;
   1.130 +		// We are going to register the system Crash monitor here so that the order
   1.131 +		// the monitor modules are placed in rom is preserved.  
   1.132 +		// The monitor is not fully intialised here.
   1.133 +		//the variant target is missing as we still have to finalise on the crash flash 
   1.134 +		//implementation. H2 & H4 doesnt support currently.
   1.135 +		LOG_CONTEXT		
   1.136 +		CLTRACE("Installing System Crash Monitor");
   1.137 +		Monitor::RegisterMonitorImpl (&TheSCMonitor );
   1.138 +		return KErrNone;
   1.139 +		}
   1.140 +	else if (aReason==KModuleEntryReasonExtensionInit0 )
   1.141 +		{
   1.142 +		return KErrNone;
   1.143 +		}
   1.144 +	else if (aReason==KModuleEntryReasonExtensionInit1 )
   1.145 +		{
   1.146 +		LOG_CONTEXT
   1.147 +		CLTRACE("Enqueing dfc to init crash flash for System Crash Monitor after all modules loaded");
   1.148 +		StartSecondaryDfc.Enque ( );
   1.149 +		return KErrNone;
   1.150 +		}
   1.151 +	return KErrArgument;
   1.152 +	}
   1.153 +
   1.154 +/**
   1.155 + Method to intialize the system crash monitor
   1.156 + @param aCategory the fault category type
   1.157 + @param aReason the reason for crash
   1.158 + @return restart type
   1.159 + */
   1.160 +TInt SCMonitor::Init2 (TAny* aCategory, TInt aReason )
   1.161 +	{
   1.162 +	LOG_CONTEXT
   1.163 +	__KTRACE_OPT(KALWAYS, Kern::Printf("\n\nSystem Crash Monitor Launched: To Analyse Crash Produced Use Core Dump Server\n"));
   1.164 +
   1.165 +	//Start logging the data:	
   1.166 +	//Need to lock kernel to access object containers (it technically is anyway, but flag isnt set)
   1.167 +	NKern::Lock();
   1.168 +	DoCrash(aCategory, aReason);	
   1.169 +	NKern::Unlock();		
   1.170 +		
   1.171 +	__KTRACE_OPT(KALWAYS, Kern::Printf("System Crash Monitor Finished: Log Size = [%d]\n", iDataSave->iCrashInf.iLogSize));
   1.172 +	
   1.173 +	return KRestartType;
   1.174 +	}
   1.175 +
   1.176 +/**
   1.177 + * This is responsible for setting up any structures required for processing of the crash
   1.178 + * @param aCategory the fault category type
   1.179 + * @param aReason 
   1.180 + */
   1.181 +void SCMonitor::DoCrash(TAny* aCategory, TInt aReason )
   1.182 +	{
   1.183 +	// get debug mask
   1.184 +	TInt dbgMask = Kern::SuperPage().iDebugMask[0];
   1.185 +	
   1.186 +	// if we are writing to the comm port then we need to turn off other debug messages
   1.187 +	if( iDataSave->GetWriteSelect() == SCMDataSave::EWriteComm)
   1.188 +		{
   1.189 +		Kern::SuperPage().iDebugMask[0] = 0;
   1.190 +		}
   1.191 +	
   1.192 +	if(!aCategory)
   1.193 +		{
   1.194 +		CLTRACE("\tNULL category retrieved and returning");
   1.195 +		TheSCMonitor.iFlash->EndTransaction();
   1.196 +		return;
   1.197 +		}
   1.198 +
   1.199 +	iFrame = NULL;
   1.200 +	
   1.201 +	CLTRACE("\tAbout to set category -- note: can occasionaly crash board");	
   1.202 +	iFaultCategory = *(const TDesC8*)aCategory;  // this crashes the board sometimes		
   1.203 +	iFaultReason = aReason;
   1.204 +	Epoc::SetMonitorExceptionHandler ((TLinAddr)HandleException );
   1.205 +	
   1.206 +	// get the first start block
   1.207 +	// will retieve start of flash by default
   1.208 +	SCMCrashBlockEntry block;
   1.209 +	TInt err = GetNextCrashStartPoint(block);  // will also attempt to read iScmConfig
   1.210 +
   1.211 +	if(KErrNone == err)
   1.212 +		{
   1.213 +		CLTRACE2("SCMonitor::DoCrash next crash will be written at blocknumber = %d offset  %d"
   1.214 +				, block.iBlockNumber, block.iBlockOffset);
   1.215 +		}
   1.216 +	else
   1.217 +		{
   1.218 +		CLTRACE1("SCMonitor::DoCrash Failed to find a valid block to write to, can not continue. err = [%d]", err);
   1.219 +		return;
   1.220 +		}
   1.221 +	
   1.222 +	TUint crashId = block.iBlockNumber;	
   1.223 +	iDataSave->iWriter->ResetBytesWritten();		
   1.224 +	
   1.225 +	//Write the crash (1st pass is to gather header data)
   1.226 +	TInt spaceRequired = ProcessCrash(block, crashId, EFalse);					
   1.227 +	
   1.228 +	// now do the real write	
   1.229 +	// prepare flash for data	
   1.230 +	TheSCMonitor.iFlash->StartTransaction();	
   1.231 +	TheSCMonitor.iFlash->SetWritePos(block.iBlockOffset);
   1.232 +
   1.233 +	//write the crash this time
   1.234 +	ProcessCrash(block, crashId, ETrue);
   1.235 +	
   1.236 +	TheSCMonitor.iFlash->EndTransaction();	
   1.237 +	
   1.238 +	// restore debug mask
   1.239 +	Kern::SuperPage().iDebugMask[0] = dbgMask;
   1.240 +	}
   1.241 +
   1.242 +
   1.243 +/**
   1.244 + * This walks the existing crash log and finds out where current crashes finish
   1.245 + * @param aBlockEntry Block to use. Only valid if KErrNone is returned.
   1.246 + * @return One of the OS wide codes
   1.247 + */
   1.248 +TInt SCMonitor::GetNextCrashStartPoint(SCMCrashBlockEntry& aBlockEntry)
   1.249 +	{
   1.250 +	LOG_CONTEXT	
   1.251 +	
   1.252 +	//First thing is to try and read the config
   1.253 +	TBool configFound = (iDataSave->ReadConfig(*iScmConfig) == KErrNone);
   1.254 +	
   1.255 +	if( iMultiCrashInfo)	
   1.256 +		{				
   1.257 +		/**
   1.258 +		 * data save has been configured to use multicrash info to find the next block we are on we need to scan each
   1.259 +		 * block to see if it contains a valid header. if we find an empty block in our block list then that is the
   1.260 +		 * one we will use if we find no empty blocks then we have no room left	
   1.261 +		 */
   1.262 +		iMultiCrashInfo->Reset();
   1.263 +		SCMCrashBlockEntry* block = iMultiCrashInfo->GetNextBlock();
   1.264 +		TBool blockFound = EFalse;				
   1.265 +		
   1.266 +		//For any crashes in flash, we need to record where they end, so that we can then go to the next
   1.267 +		//block after the one in which it ends
   1.268 +		TInt crashEndPoint = 0;		
   1.269 +		
   1.270 +		while(block)
   1.271 +			{	
   1.272 +			CLTRACE1("SCMonitor::GetNextCrashStartPoint Processing block number %d", block->iBlockNumber );			
   1.273 +			
   1.274 +			//If we have already found our block, we should erase subsequent ones for use
   1.275 +			if(blockFound)
   1.276 +				{
   1.277 +				TInt err = EraseFlashBlock(*block);
   1.278 +				if(err != KErrNone)
   1.279 +					{					
   1.280 +					return err;
   1.281 +					}
   1.282 +				
   1.283 +				block = iMultiCrashInfo->GetNextBlock(); 
   1.284 +				continue;
   1.285 +				}	
   1.286 +			
   1.287 +			//is this block before a crash end? if it is, we cant use it as a crash can span multiple blocks
   1.288 +			if(block->iBlockOffset >= crashEndPoint)
   1.289 +				{
   1.290 +				//special condition if we have a config
   1.291 +				TUint startPos = block->iBlockOffset;
   1.292 +				TUint skipBytes = 0;
   1.293 +				if(configFound && block->iBlockOffset == 0)
   1.294 +					{
   1.295 +					startPos+=iScmConfig->GetSize();
   1.296 +					
   1.297 +					//must align to flash for read
   1.298 +					skipBytes = startPos % KFlashAlignment;	
   1.299 +					startPos -= skipBytes;
   1.300 +					}
   1.301 +				
   1.302 +				// try and read an info header at these flash coords
   1.303 +				TBuf8<TCrashInfoHeader::KSCMCrashInfoMaxSize + KFlashAlignment> buf;
   1.304 +				buf.SetLength(TCrashInfoHeader::KSCMCrashInfoMaxSize + KFlashAlignment);
   1.305 +	
   1.306 +				CLTRACE1("(SCMonitor::GetNextCrashStartPoint) reading at offset %d", block->iBlockOffset);
   1.307 +				
   1.308 +				TheSCMonitor.iFlash->SetReadPos(startPos);
   1.309 +				TheSCMonitor.iFlash->Read(buf);
   1.310 +				
   1.311 +				// create the buffer applying the offset of bytes skipped
   1.312 +				TByteStreamReader reader(const_cast<TUint8*> (buf.Ptr() + skipBytes));
   1.313 +				
   1.314 +				TCrashInfoHeader header;								
   1.315 +				TInt err = header.Deserialize(reader);
   1.316 +				
   1.317 +				if(err == KErrCorrupt)
   1.318 +					{
   1.319 +					CLTRACE2("(SCMonitor::GetNextCrashStartPoint) Found empty block blocknumber %d blockoffset = %d"
   1.320 +							, block->iBlockNumber, block->iBlockOffset);
   1.321 +										
   1.322 +					blockFound = ETrue;
   1.323 +					aBlockEntry = *block;
   1.324 +					
   1.325 +					continue; //Dont get next block, as next run will erase this current block for use
   1.326 +					}
   1.327 +				else
   1.328 +					{					
   1.329 +					crashEndPoint = header.iLogSize + startPos;
   1.330 +					CLTRACE3("(SCMonitor::GetNextCrashStartPoint) In block [%d] we found a valid crash header. This crash finishes at [%d] [0x%X]", block->iBlockNumber, crashEndPoint, crashEndPoint);
   1.331 +					}
   1.332 +				}
   1.333 +			
   1.334 +			block = iMultiCrashInfo->GetNextBlock();
   1.335 +			}									
   1.336 +			
   1.337 +		if(blockFound)
   1.338 +			{
   1.339 +			return KErrNone;
   1.340 +			}
   1.341 +		else
   1.342 +			{
   1.343 +			//CLTRACE("(SCMonitor::GetNextCrashStartPoint) No available blocks TREATING as NO MULTICRASH INFO will write to default block");
   1.344 +			//In this case should we just overwrite old crashes and return the first block as the comment above suggests
   1.345 +			//return blockFound;
   1.346 +			}
   1.347 +		}
   1.348 +
   1.349 +	// no multi crash info supplied - use default first block settings
   1.350 +	TInt err = EraseEntireFlashPartition();
   1.351 +	if(err != KErrNone)
   1.352 +		{
   1.353 +		CLTRACE1("Unable to delete area required to log to flash. Aborting. Error - [%d]", err);
   1.354 +		return err;
   1.355 +		}
   1.356 +	
   1.357 +	aBlockEntry = SCMCrashBlockEntry(0,0,0);
   1.358 +	return KErrNone;
   1.359 +	}
   1.360 +
   1.361 +/**
   1.362 + * Handles the processing of the crash
   1.363 + * @return The size of the crash log (including header) that has been/will be written
   1.364 + */
   1.365 +TInt SCMonitor::ProcessCrash(const SCMCrashBlockEntry& aBlock, TUint aCrashId, TBool aCommit)
   1.366 +	{	
   1.367 +	LOG_CONTEXT
   1.368 +	CLTRACE5("aBlock.iBlockOffset = [%d]  [0x%X] aBlock.iBlockNumber = %d aBlock.iBlockSize = [%d]  [0x%X]",
   1.369 +			aBlock.iBlockOffset, aBlock.iBlockOffset, aBlock.iBlockNumber, aBlock.iBlockSize, aBlock.iBlockSize);		
   1.370 +	
   1.371 +	// reset writer for start of each crash
   1.372 +	iDataSave->iWriter->ResetBytesWritten();
   1.373 +	TInt logLevel = 0;
   1.374 +
   1.375 +	if(aCommit)
   1.376 +		{
   1.377 +		logLevel = KALWAYS;
   1.378 +		iDataSave->iWriter->EnablePhysicalWriting();	
   1.379 +		}
   1.380 +	else
   1.381 +		{
   1.382 +#if defined(_DEBUG)
   1.383 +		logLevel = KDEBUGGER;
   1.384 +#else
   1.385 +		logLevel = KALWAYS; //Doesnt matter, KTRACE OPT is empty for rel builds 
   1.386 +		if(logLevel != KALWAYS)
   1.387 +			{
   1.388 +			//This is to avoid warning
   1.389 +			}
   1.390 +#endif
   1.391 +		
   1.392 +		iDataSave->iWriter->DisablePhysicalWriting();	
   1.393 +		}
   1.394 +	
   1.395 +	iDataSave->SetByteCount(aBlock.iBlockOffset);	
   1.396 +	if(aBlock.iBlockOffset == 0 && aBlock.iBlockNumber == 0)
   1.397 +		{	
   1.398 +		// this is the first crash - we need to save the config here first
   1.399 +		CLTRACE("(SCMonitor::ProcessCrash) - this is block 0 - WRITING CONFIG");
   1.400 +		iDataSave->LogConfig(*iScmConfig);	
   1.401 +		
   1.402 +		//Config is not part of crash so reset bytes written			
   1.403 +		iDataSave->SetCrashStartingPoint(iDataSave->iWriter->GetBytesWritten());		
   1.404 +		}	
   1.405 +	else
   1.406 +		{
   1.407 +		iDataSave->SetCrashStartingPoint(aBlock.iBlockOffset);
   1.408 +		}	
   1.409 +	
   1.410 +	iDataSave->iWriter->ResetBytesWritten();
   1.411 +	
   1.412 +	TUint32 logSize = 0;
   1.413 +	TUint sizeOfObjectDumped = 0;
   1.414 +		
   1.415 +	TInt err = iDataSave->LogCrashHeader(iFaultCategory, iFaultReason, aCrashId, sizeOfObjectDumped);		
   1.416 +	if(KErrNone != err)
   1.417 +		{
   1.418 +		CLTRACE("System Crash Monitor: Failed to create crash info header - (TCrashInfo)"); 
   1.419 +		return KRestartType;
   1.420 +		}	
   1.421 +	
   1.422 +	logSize += sizeOfObjectDumped;
   1.423 +	
   1.424 +	//Now we must read the configuration to use. This is held at the start of our flash partition
   1.425 +	//and managed by the iConfig object
   1.426 +	iScmConfig->ResetToHighestPriority();	
   1.427 +		
   1.428 +	//Always want the crash context
   1.429 +	iDataSave->iHdr.iCTFullRegOffset = logSize + iDataSave->GetCrashStartingPoint();
   1.430 +	
   1.431 +	err = iDataSave->LogCPURegisters(sizeOfObjectDumped);
   1.432 +	if(KErrNone != err)
   1.433 +		{
   1.434 +		CLTRACE1("\tError logging full registers = %d", err);
   1.435 +		}	
   1.436 +	
   1.437 +	logSize += sizeOfObjectDumped;
   1.438 +	
   1.439 +	CLTRACE("\tAbout to enter processing loop");		
   1.440 +	SCMDataSave::TDataToDump dump;
   1.441 +		
   1.442 +	for(;;)		
   1.443 +		{		
   1.444 +		//now we get each item by priority from the configuration
   1.445 +		TConfigItem* configItem = iScmConfig->GetNextItem();
   1.446 +
   1.447 +		if(!configItem)
   1.448 +			{
   1.449 +			// end of list
   1.450 +			break;
   1.451 +			}
   1.452 +		
   1.453 +		CLTRACE1("\nLooking at item type [%d]", configItem->GetDataType());
   1.454 +		if(configItem->GetSpaceRequired() > iDataSave->SpaceRemaining())
   1.455 +			{
   1.456 +			__KTRACE_OPT(logLevel, Kern::Printf("\t\tFor Item Type [%d]: Unable to log [0x%X] [%d] bytes because we only have [0x%X] [%d] bytes left", configItem->GetDataType(), configItem->GetSpaceRequired(), configItem->GetSpaceRequired(), iDataSave->SpaceRemaining(), iDataSave->SpaceRemaining()));
   1.457 +			continue;
   1.458 +			}
   1.459 +		else
   1.460 +			{
   1.461 +			CLTRACE1("Will require [%d] bytes for this item", configItem->GetSpaceRequired());
   1.462 +			}
   1.463 +		
   1.464 +		// only interested in logging items with priority > 0
   1.465 +		if( configItem->GetPriority() <= 0)
   1.466 +			{
   1.467 +			CLTRACE1("\tIgnored config item type %d priority 0", configItem->GetDataType());
   1.468 +			continue;
   1.469 +			}
   1.470 +			
   1.471 +		//there are a lot of TUints in the hdr to record where we wrote this item. 
   1.472 +		//This will point to the one of interest for this configItem
   1.473 +		TUint32* offsetPointer = NULL;				
   1.474 +		
   1.475 +		//now we check the type of data we wish to dump
   1.476 +		switch(configItem->GetDataType())
   1.477 +			{
   1.478 +			case TConfigItem::ECrashedThreadMetaData:			
   1.479 +				{
   1.480 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedThreadMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.481 +				
   1.482 +				err = LogThreadMetaData(SCMDataSave::EThreadSpecific, sizeOfObjectDumped);
   1.483 +				offsetPointer = &(iDataSave->iHdr.iCTMetaOffset);
   1.484 +				
   1.485 +				break;
   1.486 +				}
   1.487 +			case TConfigItem::EThreadsMetaData:			
   1.488 +				{
   1.489 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.490 +				
   1.491 +				//record location we are writing to in the header
   1.492 +				iDataSave->iHdr.iTLstOffset = iDataSave->iWriter->GetBytesWritten();
   1.493 +				err = LogThreadMetaData(SCMDataSave::ESystemWide, sizeOfObjectDumped);
   1.494 +				offsetPointer = &(iDataSave->iHdr.iTLstOffset);
   1.495 +				
   1.496 +				break;
   1.497 +				}
   1.498 +			case TConfigItem::ECrashedProcessMetaData:			
   1.499 +				{
   1.500 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.501 +					
   1.502 +				err = LogProcessMetaData(SCMDataSave::EProcessSpecific, sizeOfObjectDumped);
   1.503 +				offsetPointer = &(iDataSave->iHdr.iCPMetaOffset);
   1.504 +				
   1.505 +				break;
   1.506 +				}
   1.507 +			case TConfigItem::EProcessMetaData:		
   1.508 +				{
   1.509 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EProcessMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.510 +								
   1.511 +				err = LogProcessMetaData(SCMDataSave::ESystemWide, sizeOfObjectDumped);
   1.512 +				offsetPointer = &(iDataSave->iHdr.iPLstOffset);
   1.513 +				
   1.514 +				break;
   1.515 +				}
   1.516 +			case TConfigItem::ECrashedProcessUsrStacks:			
   1.517 +				{
   1.518 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessUsrStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.519 +								
   1.520 +				//define what we wish to dump
   1.521 +				dump.iMetaData = EFalse;
   1.522 +				dump.iCodeSegs = EFalse;
   1.523 +				dump.iStk = SCMDataSave::EUsrStack;
   1.524 +				dump.iReg = SCMDataSave::ERegSetNone;	
   1.525 +				err = LogObjectContainers(EThread, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);	
   1.526 +				offsetPointer = &(iDataSave->iHdr.iCTUsrStkOffset);
   1.527 +				
   1.528 +				break;
   1.529 +				}
   1.530 +			case TConfigItem::EThreadsUsrStack:			
   1.531 +				{
   1.532 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsUsrStack at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.533 +				
   1.534 +				//define what we wish to dump
   1.535 +				dump.iMetaData = EFalse;
   1.536 +				dump.iCodeSegs = EFalse;
   1.537 +				dump.iStk = SCMDataSave::EUsrStack;
   1.538 +				dump.iReg = SCMDataSave::ERegSetNone;
   1.539 +
   1.540 +				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
   1.541 +				offsetPointer = &(iDataSave->iHdr.iSysSvrStkOffset);
   1.542 +				
   1.543 +				break;
   1.544 +				}
   1.545 +			case TConfigItem::ECrashedProcessSvrStacks:			
   1.546 +				{
   1.547 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessSvrStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.548 +								
   1.549 +				//define what we wish to dump
   1.550 +				dump.iMetaData = EFalse;
   1.551 +				dump.iCodeSegs = EFalse;
   1.552 +				dump.iStk = SCMDataSave::ESvrStack;
   1.553 +				dump.iReg = SCMDataSave::ERegSetNone;
   1.554 +				
   1.555 +				err = LogObjectContainers(EThread, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);
   1.556 +				offsetPointer = &(iDataSave->iHdr.iCTSvrStkOffset);
   1.557 +				
   1.558 +				break;
   1.559 +				}
   1.560 +			case TConfigItem::EThreadsSvrStack:			
   1.561 +				{
   1.562 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsSvrStack at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.563 +								
   1.564 +				//define what we wish to dump
   1.565 +				dump.iMetaData = EFalse;
   1.566 +				dump.iCodeSegs = EFalse;
   1.567 +				dump.iStk = SCMDataSave::ESvrStack;
   1.568 +				dump.iReg = SCMDataSave::ERegSetNone;
   1.569 +				
   1.570 +				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
   1.571 +				offsetPointer = &(iDataSave->iHdr.iSysSvrStkOffset);
   1.572 +				
   1.573 +				break;
   1.574 +				}
   1.575 +			case TConfigItem::EThreadsUsrRegisters:		
   1.576 +				{
   1.577 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsUsrRegisters at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.578 +								
   1.579 +				//define what we wish to dump
   1.580 +				dump.iMetaData = EFalse;
   1.581 +				dump.iCodeSegs = EFalse;
   1.582 +				dump.iStk = SCMDataSave::EStackTypeNone;
   1.583 +				dump.iReg = SCMDataSave::EUserRegisters;
   1.584 +				
   1.585 +				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
   1.586 +				offsetPointer = &(iDataSave->iHdr.iSysUsrRegOffset);
   1.587 +				
   1.588 +				break;
   1.589 +				}
   1.590 +			case TConfigItem::EThreadsSvrRegisters:		
   1.591 +				{
   1.592 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsSvrRegisters at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.593 +								
   1.594 +				//define what we wish to dump
   1.595 +				dump.iMetaData = EFalse;
   1.596 +				dump.iCodeSegs = EFalse;
   1.597 +				dump.iStk = SCMDataSave::EStackTypeNone;
   1.598 +				dump.iReg = SCMDataSave::ESupervisorRegisters;
   1.599 +				
   1.600 +				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
   1.601 +				offsetPointer = &(iDataSave->iHdr.iSysSvrRegOffset);
   1.602 +				
   1.603 +				break;
   1.604 +				}
   1.605 +			case TConfigItem::EExceptionStacks:
   1.606 +				{
   1.607 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EExceptionStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.608 +							
   1.609 +				err = iDataSave->LogExceptionStacks(sizeOfObjectDumped);
   1.610 +				offsetPointer = &(iDataSave->iHdr.iExcStkOffset);
   1.611 +				
   1.612 +				break;
   1.613 +				}
   1.614 +			case TConfigItem::ECrashedProcessCodeSegs:
   1.615 +				{	
   1.616 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessCodeSegs at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.617 +								
   1.618 +				//define what we wish to dump
   1.619 +				dump.iMetaData = EFalse;
   1.620 +				dump.iCodeSegs = ETrue;
   1.621 +				dump.iStk = SCMDataSave::EStackTypeNone;
   1.622 +				dump.iReg = SCMDataSave::ERegSetNone;				
   1.623 +				
   1.624 +				err = LogObjectContainers(EProcess, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);
   1.625 +				offsetPointer = &(iDataSave->iHdr.iCPCodeSegOffset);
   1.626 +				
   1.627 +				break;
   1.628 +				}
   1.629 +			case TConfigItem::EProcessCodeSegs:
   1.630 +				{
   1.631 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EProcessCodeSegs at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.632 +								
   1.633 +				//define what we wish to dump
   1.634 +				dump.iMetaData = EFalse;
   1.635 +				dump.iCodeSegs = ETrue;
   1.636 +				dump.iStk = SCMDataSave::EStackTypeNone;
   1.637 +				dump.iReg = SCMDataSave::ERegSetNone;
   1.638 +				err = LogObjectContainers(EProcess, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
   1.639 +				offsetPointer = &(iDataSave->iHdr.iSysCodeSegOffset);
   1.640 +				
   1.641 +				break;
   1.642 +				}
   1.643 +			case TConfigItem::ETraceData:
   1.644 +				{
   1.645 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ETraceData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.646 +									
   1.647 +				err = iDataSave->LogTraceBuffer(configItem->GetSizeToDump(), sizeOfObjectDumped);
   1.648 +				offsetPointer = &(iDataSave->iHdr.iTraceOffset);
   1.649 +				
   1.650 +				break;
   1.651 +				}		
   1.652 +			case TConfigItem::ELocks:
   1.653 +				{
   1.654 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ELocks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));	
   1.655 +					
   1.656 +				err = iDataSave->LogLocks(sizeOfObjectDumped);
   1.657 +				offsetPointer = &(iDataSave->iHdr.iScmLocksOffset);
   1.658 +				
   1.659 +				break;
   1.660 +				}
   1.661 +			case TConfigItem::EKernelHeap:
   1.662 +				{
   1.663 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EKernelHeap at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.664 +				
   1.665 +				err = iDataSave->LogKernelHeap(sizeOfObjectDumped);
   1.666 +				offsetPointer = &(iDataSave->iHdr.iKernelHeapOffset);
   1.667 +				
   1.668 +				break;
   1.669 +				}
   1.670 +			case TConfigItem::EVariantSpecificData:
   1.671 +				{
   1.672 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EVariantSpecificData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.673 +				
   1.674 +				err = iDataSave->LogVariantSpecificData(sizeOfObjectDumped);
   1.675 +				offsetPointer = &(iDataSave->iHdr.iVarSpecInfOffset);
   1.676 +				
   1.677 +				break;
   1.678 +				}
   1.679 +			case TConfigItem::ERomInfo:
   1.680 +				{
   1.681 +				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ERomInfo at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
   1.682 +				
   1.683 +				err = iDataSave->LogRomInfo(sizeOfObjectDumped);
   1.684 +				offsetPointer = &(iDataSave->iHdr.iRomInfoOffset);
   1.685 +				
   1.686 +				break;
   1.687 +				}
   1.688 +			//unknown configuration type - something bad is going on
   1.689 +			default: return 0;			
   1.690 +			}				
   1.691 +		
   1.692 +		if(KErrNone != err)
   1.693 +			{
   1.694 +			__KTRACE_OPT(logLevel, Kern::Printf("\tError logging data: [%d]   Type = [%d]", err, aBlock.iBlockOffset));
   1.695 +			continue;
   1.696 +			}
   1.697 +		
   1.698 +		//Set the space required so next time around we will know in advance how much space we need
   1.699 +		configItem->SetSpaceRequired(sizeOfObjectDumped);		
   1.700 +		
   1.701 +		//Note: the following steps are only required for the first time we call process crash. The second time,
   1.702 +		//when physical writing is enabled, these will have been written already and so they dont matter
   1.703 +		
   1.704 +		//update the offset and logsize if we are going to dump this item
   1.705 +		TUint32 absoluteLogPos = logSize + iDataSave->GetCrashStartingPoint();
   1.706 +		if(absoluteLogPos+sizeOfObjectDumped < iDataSave->MaxLogSize())
   1.707 +			{
   1.708 +			//now, we must record where in the crash log this item will be dumped
   1.709 +			*offsetPointer = absoluteLogPos;
   1.710 +			logSize += sizeOfObjectDumped;
   1.711 +			}
   1.712 +		}
   1.713 +	
   1.714 +	iDataSave->iCrashInf.iLogSize = logSize;	
   1.715 +	iDataSave->iWriter->FlushCache();		
   1.716 +	
   1.717 +	return iDataSave->iCrashInf.iLogSize;
   1.718 +	}
   1.719 +
   1.720 +/**
   1.721 + * Logs the meta data for processes
   1.722 + * @param aCurrentProcess - scope to dump
   1.723 + * @return one of the OS wide codes
   1.724 + */
   1.725 +TInt SCMonitor::LogProcessMetaData(SCMDataSave::TDumpScope aScope, TUint& aSizeDumped) const
   1.726 +	{
   1.727 +	LOG_CONTEXT
   1.728 +	
   1.729 +	SCMDataSave::TDataToDump dump;
   1.730 +	dump.iMetaData = ETrue;
   1.731 +	
   1.732 +	return LogObjectContainers(EProcess, aScope, dump, aSizeDumped);
   1.733 +	}
   1.734 +
   1.735 +/**
   1.736 + * 
   1.737 + * @param aCurrentThread -  to only do the current (crashed thread) or to do all the others
   1.738 + * @return one of the OS wide codes
   1.739 + */
   1.740 +TInt SCMonitor::LogThreadMetaData(SCMDataSave::TDumpScope aScope, TUint& aSizeDumped) const
   1.741 +	{
   1.742 +	LOG_CONTEXT
   1.743 +	
   1.744 +	SCMDataSave::TDataToDump dump; 
   1.745 +	dump.iMetaData = ETrue;
   1.746 +	
   1.747 +	return LogObjectContainers(EThread, aScope, dump, aSizeDumped);
   1.748 +	}
   1.749 +
   1.750 +/**
   1.751 + * Generic method that looks at all kernel objects of aObjectType
   1.752 + * @param aObjectType
   1.753 + * @param aDumpScope - if you wish to dump for the the current process, current thread or entire system
   1.754 + * @param aDataToDump - data you wish to dump
   1.755 + * @param aSizeDumped - records how much was dumped
   1.756 + * @return
   1.757 + */
   1.758 +TInt SCMonitor::LogObjectContainers(TObjectType aObjectType, SCMDataSave::TDumpScope aDumpScope, const SCMDataSave::TDataToDump& aDataToDump, TUint& aSizeDumped) const
   1.759 +	{
   1.760 +	aSizeDumped = 0;
   1.761 +	
   1.762 +	if(aObjectType >= ENumObjectTypes)
   1.763 +		{
   1.764 +		return KErrArgument;
   1.765 +		}
   1.766 +	
   1.767 +	//Get the object container for the given object type
   1.768 +	DObjectCon* objectContainer = Kern::Containers()[aObjectType];
   1.769 +	if(objectContainer == NULL)
   1.770 +		{		
   1.771 +		CLTRACE("tFailed to get object container");
   1.772 +		return KErrNotFound;
   1.773 +		}
   1.774 +	
   1.775 +	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
   1.776 +	if(objectContainer->iMutex->iHoldCount)
   1.777 +		{
   1.778 +		CLTRACE("\tObject Container is in an inconsistant state");
   1.779 +		return KErrCorrupt;
   1.780 +		}
   1.781 +	
   1.782 +	TInt numObjects = objectContainer->Count();
   1.783 +	TInt err = KErrNone;	
   1.784 +	
   1.785 +	for(TInt cnt = 0; cnt< numObjects; cnt ++)
   1.786 +		{	
   1.787 +		DObject* object = (*objectContainer)[cnt];
   1.788 +		
   1.789 +		//Are we interested in the object? scope only relevant for thread and process objects, for others, the scope is implicit
   1.790 +		if(aObjectType == EThread)			
   1.791 +			{
   1.792 +			switch(aDumpScope)
   1.793 +				{
   1.794 +				case SCMDataSave::EThreadSpecific :
   1.795 +					{
   1.796 +					//if we are interested in the current thread and this is not it, continue
   1.797 +					if(((DThread*)object) != &Kern::CurrentThread())
   1.798 +						continue;
   1.799 +					break;
   1.800 +					}
   1.801 +				case SCMDataSave::EProcessSpecific :
   1.802 +					{
   1.803 +					//if we are interested in the current proc and this is not it, continue
   1.804 +					if(((DThread*)object)->iOwningProcess != &Kern::CurrentProcess())
   1.805 +						continue;					
   1.806 +					break;
   1.807 +					}
   1.808 +				case SCMDataSave::ESystemWide :
   1.809 +				default: 
   1.810 +					break;
   1.811 +				}
   1.812 +			}
   1.813 +		else if(aObjectType == EProcess)
   1.814 +			{
   1.815 +			switch(aDumpScope)
   1.816 +				{
   1.817 +				case SCMDataSave::EProcessSpecific :
   1.818 +					{
   1.819 +					if((DProcess*)object != &Kern::CurrentProcess())
   1.820 +						continue;
   1.821 +					break;
   1.822 +					}
   1.823 +				case SCMDataSave::EThreadSpecific :  //thread specific process doesnt make sense
   1.824 +					return KErrArgument;				
   1.825 +				case SCMDataSave::ESystemWide :
   1.826 +				default:
   1.827 +					break;
   1.828 +				}
   1.829 +			}
   1.830 +		
   1.831 +		//Now we look at the data we have been asked to dump
   1.832 +		if(aDataToDump.iMetaData)
   1.833 +			{
   1.834 +			TUint dumped = 0;
   1.835 +			err = HelpDumpMetaData(object, aObjectType, dumped);
   1.836 +			if(KErrNone != err)
   1.837 +				{
   1.838 +				CLTRACE1("Failed to meta data: [%d]", err);
   1.839 +				return err;
   1.840 +				}
   1.841 +			aSizeDumped += dumped;
   1.842 +			}
   1.843 +		
   1.844 +		if(aDataToDump.iCodeSegs)
   1.845 +			{
   1.846 +			if(aObjectType != EProcess)
   1.847 +				{
   1.848 +				return KErrArgument;
   1.849 +				}
   1.850 +			
   1.851 +			TUint dumped = 0;
   1.852 +			err = iDataSave->LogCodeSegments((DProcess*)object, dumped);
   1.853 +			if(KErrNone != err)
   1.854 +				{
   1.855 +				CLTRACE1("Failed to log code segments: [%d]", err);
   1.856 +				return err;
   1.857 +				}
   1.858 +			aSizeDumped += dumped;
   1.859 +			}
   1.860 +		
   1.861 +		if(aDataToDump.iStk != SCMDataSave::EStackTypeNone)
   1.862 +			{
   1.863 +			TUint dumped = 0;
   1.864 +			err = HelpDumpStacks(object, aObjectType, dumped, aDataToDump.iStk);
   1.865 +			if(KErrNone != err)
   1.866 +				{
   1.867 +				CLTRACE1("Failed to log stacks: [%d]", err);
   1.868 +				return err;
   1.869 +				}
   1.870 +			aSizeDumped += dumped;
   1.871 +			}
   1.872 +		
   1.873 +		if(aDataToDump.iReg != SCMDataSave::ERegSetNone)
   1.874 +			{			
   1.875 +			if(aObjectType != EThread)
   1.876 +				{
   1.877 +				return KErrArgument;
   1.878 +				}
   1.879 +			TUint dumped = 0;
   1.880 +			err = iDataSave->LogRegisters((DThread*)object, aDataToDump.iReg, dumped);	
   1.881 +			if(KErrNone != err && KErrNotSupported !=err)  //we expect to send down a KErrNotSupported when we ask for Full CPU set for the non crashed thread - thats fine
   1.882 +				{
   1.883 +				CLTRACE1("Failed to log registers: [%d]", err);
   1.884 +				return err;
   1.885 +				}
   1.886 +			aSizeDumped += dumped;
   1.887 +			}
   1.888 +		}
   1.889 +	
   1.890 +	return KErrNone;
   1.891 +	}
   1.892 +
   1.893 +/**
   1.894 + * Helper method for dumping stacks. Looks to see what type of stack we want and then calls
   1.895 + * appropriate method
   1.896 + * @param aObject The DThread object whose stack we want
   1.897 + * @param aObjectType The object type of this aObject. Anything other than EThread will give KErrArgument
   1.898 + * @param aSizeDumped Holds the size of the stack dumped after processing 
   1.899 + * @param aStkType The type of stack to be dumped
   1.900 + * @see TObjectType
   1.901 + * @see SCMDataSave::TStackType
   1.902 + * @return One of the system wide codes
   1.903 + */
   1.904 +TInt SCMonitor::HelpDumpStacks(DObject* aObject, TObjectType aObjectType, TUint& aSizeDumped, SCMDataSave::TStackType aStkType) const
   1.905 +	{
   1.906 +	//verify args
   1.907 +	if(aObjectType != EThread)
   1.908 +		{
   1.909 +		return KErrArgument;
   1.910 +		}
   1.911 +	
   1.912 +	switch(aStkType)
   1.913 +		{
   1.914 +		case SCMDataSave::EUsrStack:
   1.915 +			{
   1.916 +			return iDataSave->LogThreadUserStack((DThread*)aObject, ETrue, aSizeDumped);
   1.917 +			}
   1.918 +		case SCMDataSave::ESvrStack:
   1.919 +			{
   1.920 +			return iDataSave->LogThreadSupervisorStack((DThread*)aObject, ETrue, aSizeDumped);
   1.921 +			}
   1.922 +		default: return KErrArgument;
   1.923 +		}
   1.924 +	}
   1.925 +
   1.926 +/**
   1.927 + * Helper method to dump meta data about a DThread or a DProcess object
   1.928 + * @param aObject DObject to use
   1.929 + * @param aObjectType Type of DObject. Must be EThread or EProcess
   1.930 + * @param aSizeDumped Holds the size of the stack dumped after processing 
   1.931 + * @return
   1.932 + */
   1.933 +TInt SCMonitor::HelpDumpMetaData(DObject* aObject, TObjectType aObjectType, TUint& aSizeDumped) const
   1.934 +	{
   1.935 +	aSizeDumped = 0;
   1.936 +	
   1.937 +	switch(aObjectType)
   1.938 +		{
   1.939 +		case EThread:
   1.940 +			{
   1.941 +			return iDataSave->LogThreadData((DThread*)aObject, aSizeDumped);	 
   1.942 +			}
   1.943 +		case EProcess:
   1.944 +			{
   1.945 +			return iDataSave->LogProcessData((DProcess*)aObject, aSizeDumped);
   1.946 +			}
   1.947 +		default: return KErrArgument;
   1.948 +		}
   1.949 +	}
   1.950 +
   1.951 +/**
   1.952 + * Wrapper method around the flash erase block fundtion to determine if the erase was succesful.
   1.953 + * If the erase was not succesful we can't continue as we cannot write.
   1.954 + * @param aBlockOffset Block to erase
   1.955 + * @return One of the OS wide codes
   1.956 + */
   1.957 +TInt SCMonitor::EraseFlashBlock(const SCMCrashBlockEntry& aBlock)
   1.958 +	{	
   1.959 +	iFlash->StartTransaction();
   1.960 +	
   1.961 +	TInt numAttempts = 0;
   1.962 +	while(numAttempts < KFlashEraseAttempts)
   1.963 +		{
   1.964 +		iFlash->SetWritePos(aBlock.iBlockOffset);
   1.965 +		iFlash->EraseFlashBlock(aBlock.iBlockOffset);
   1.966 +		
   1.967 +		//we will read the flash to make sure that it set the block to all 1's (well not all, just the start)
   1.968 +		TBuf8<sizeof(TUint32)> buf;
   1.969 +		buf.SetLength(sizeof(TUint32));
   1.970 +				
   1.971 +		iFlash->SetReadPos(aBlock.iBlockOffset);
   1.972 +		iFlash->Read(buf);
   1.973 +		
   1.974 +		volatile TUint32* result = (TUint32*)buf.Ptr();
   1.975 +		if(*result == 0xFFFFFFFF)
   1.976 +			{			
   1.977 +			__KTRACE_OPT(KALWAYS, Kern::Printf("Erase of block [0x%X] succesful after [%d] attempts", aBlock.iBlockOffset, numAttempts+1))			
   1.978 +			iFlash->EndTransaction();			
   1.979 +			return KErrNone;
   1.980 +			}
   1.981 +		
   1.982 +		numAttempts++;
   1.983 +		
   1.984 +		//Sometimes a write to the block helps the next erase
   1.985 +		TUint32 bytesWritten = 0;		
   1.986 +		while(bytesWritten < aBlock.iBlockSize)
   1.987 +			{
   1.988 +			TBuf8<sizeof(TUint8)> num;
   1.989 +			num.Append(0x0);
   1.990 +			iFlash->Write(num);
   1.991 +			bytesWritten++;
   1.992 +			}
   1.993 +		}		
   1.994 +
   1.995 +	__KTRACE_OPT(KALWAYS, Kern::Printf("After %d attempts, we were unable to erase the flash block at [0x%X]. This could be because "
   1.996 +			"the driver is defective or because the flash has gone past its lifetime. Whatever it is though, "
   1.997 +			"we cannot continue.", KFlashEraseAttempts, aBlock.iBlockOffset));
   1.998 +	
   1.999 +	iFlash->EndTransaction();
  1.1000 +	return KErrAbort;
  1.1001 +	}
  1.1002 +
  1.1003 +/**
  1.1004 + * This erases each block in the flash partition
  1.1005 + * @return One of the system wide codes
  1.1006 + */
  1.1007 +TInt SCMonitor::EraseEntireFlashPartition()
  1.1008 +	{
  1.1009 +	if(iMultiCrashInfo)
  1.1010 +		{
  1.1011 +		iMultiCrashInfo->Reset();
  1.1012 +		
  1.1013 +		SCMCrashBlockEntry* block = iMultiCrashInfo->GetNextBlock();
  1.1014 +		while(block)
  1.1015 +			{
  1.1016 +			TInt err = EraseFlashBlock(*block);
  1.1017 +			if(KErrNone != err)
  1.1018 +				{
  1.1019 +				return err;
  1.1020 +				}
  1.1021 +			
  1.1022 +			block = iMultiCrashInfo->GetNextBlock();
  1.1023 +			}
  1.1024 +		
  1.1025 +		return KErrNone;
  1.1026 +		}
  1.1027 +	
  1.1028 +	CLTRACE("SCMonitor::EraseEntireFlashPartition() -- No Flash MAP available, trying to use the raw driver to delete.");
  1.1029 +	TheSCMonitor.iFlash->EraseLogArea();
  1.1030 +	
  1.1031 +	return KErrNone;
  1.1032 +	}
  1.1033 +
  1.1034 +//eof scmonitor.cpp
  1.1035 +