os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/scmonitor.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\debug\crashMonitor\src\scmonitor.cpp
sl@0
    15
// Core dump server - Kernel side crash monitor
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
 @internalTechnology
sl@0
    22
*/
sl@0
    23
sl@0
    24
#include <scmonitor.h>
sl@0
    25
#include <kernel/monitor.h>
sl@0
    26
#include <assp.h>
sl@0
    27
#include <drivers/crashflash.h>
sl@0
    28
#include <kernel/klib.h>
sl@0
    29
#include <crashlogwalker.h>
sl@0
    30
#include <scmconfigitem.h>
sl@0
    31
sl@0
    32
#include "scmdatasave.h"
sl@0
    33
sl@0
    34
GLDEF_D SCMonitor TheSCMonitor; //global definition of SCMonitor
sl@0
    35
sl@0
    36
//keep things 4 byte aligned
sl@0
    37
const TInt KRestartType = SCMonitor::ESoftRestart;
sl@0
    38
sl@0
    39
/**
sl@0
    40
SCMonitor constructor
sl@0
    41
*/
sl@0
    42
SCMonitor::SCMonitor()
sl@0
    43
	: iMultiCrashInfo(NULL)
sl@0
    44
	{
sl@0
    45
	}
sl@0
    46
sl@0
    47
SCMonitor::~SCMonitor()
sl@0
    48
	{
sl@0
    49
	delete iMultiCrashInfo;
sl@0
    50
	}
sl@0
    51
sl@0
    52
/**
sl@0
    53
 Print data to the corresponding output channel. Derived from monitor
sl@0
    54
 @param aDes the buffer containing the data
sl@0
    55
 */
sl@0
    56
void SCMonitor::Print (const TDesC8& aDes )
sl@0
    57
	{
sl@0
    58
	//intended to do nothing
sl@0
    59
	}
sl@0
    60
sl@0
    61
/**
sl@0
    62
 * Allocates resources for SCMonitor
sl@0
    63
 * cant fully construct in constructor as we are a kernel extension and resources are limited when we are created
sl@0
    64
 */
sl@0
    65
void SCMonitor::StableConstruction()
sl@0
    66
	{
sl@0
    67
	LOG_CONTEXT
sl@0
    68
	iDataSave = new SCMDataSave(this, TheSCMonitor.iFlash);	
sl@0
    69
	
sl@0
    70
	//Configuration object for use upon crash
sl@0
    71
	iScmConfig = new SCMConfiguration();
sl@0
    72
	TInt err = iScmConfig->SetDefaultConfig();	
sl@0
    73
	if(KErrNone != err)
sl@0
    74
		{
sl@0
    75
		CLTRACE1("SCMonitor::StableConstruction - Unable to set default config err = %d", err);
sl@0
    76
		}
sl@0
    77
	
sl@0
    78
	
sl@0
    79
#ifdef NO_MULTICRASHINFO	
sl@0
    80
	iMultiCrashInfo = NULL;
sl@0
    81
#else	
sl@0
    82
sl@0
    83
	//We need to take a look at the flash map from variant_norflash_layout.h
sl@0
    84
	iMultiCrashInfo = new SCMMultiCrashInfo();
sl@0
    85
sl@0
    86
	TUint numberBlocks = KCrashLogSize / KCrashLogBlockSize;
sl@0
    87
	for(TUint32 cnt = 0; cnt < numberBlocks; cnt++)
sl@0
    88
		{
sl@0
    89
		iMultiCrashInfo->AddBlock(new SCMCrashBlockEntry(cnt, cnt * KCrashLogBlockSize, KCrashLogBlockSize));
sl@0
    90
		}
sl@0
    91
#endif
sl@0
    92
	}
sl@0
    93
sl@0
    94
/**
sl@0
    95
 * Start a secondary DFC queue for the Flash and Init the flash in the variant(h4)
sl@0
    96
 * @param aAny
sl@0
    97
 */
sl@0
    98
void StartSecondary (TAny* )
sl@0
    99
	{
sl@0
   100
	LOG_CONTEXT
sl@0
   101
	//InitFlash is implemented in the variant as it creates a variant
sl@0
   102
	//specific derived CrashFlash
sl@0
   103
	TheSCMonitor.InitFlash ( );
sl@0
   104
	TheSCMonitor.StableConstruction();
sl@0
   105
	}
sl@0
   106
sl@0
   107
/**
sl@0
   108
 * Global method to create a dfc queue
sl@0
   109
 * @param Method to intialise the flash.
sl@0
   110
 * @param Null
sl@0
   111
 * @param Gets the address of the supervisor thread DFC queue
sl@0
   112
 * @param TDfcQ priority number
sl@0
   113
 * @return a DFC object
sl@0
   114
 */
sl@0
   115
GLDEF_C TDfc StartSecondaryDfc(&StartSecondary, NULL, Kern::SvMsgQue(), KMaxDfcPriority-1);
sl@0
   116
sl@0
   117
/**
sl@0
   118
 * Kernel Main module entry - Own implementation( similar to crash logger)
sl@0
   119
 * @param aReason reason to enter to the method
sl@0
   120
 * @return One of the system wide codes
sl@0
   121
 */
sl@0
   122
GLDEF_C TInt KernelModuleEntry(TInt aReason)
sl@0
   123
	{	
sl@0
   124
	if(aReason==KModuleEntryReasonVariantInit0)
sl@0
   125
		{
sl@0
   126
		new(&TheSCMonitor) SCMonitor;
sl@0
   127
		// We are going to register the system Crash monitor here so that the order
sl@0
   128
		// the monitor modules are placed in rom is preserved.  
sl@0
   129
		// The monitor is not fully intialised here.
sl@0
   130
		//the variant target is missing as we still have to finalise on the crash flash 
sl@0
   131
		//implementation. H2 & H4 doesnt support currently.
sl@0
   132
		LOG_CONTEXT		
sl@0
   133
		CLTRACE("Installing System Crash Monitor");
sl@0
   134
		Monitor::RegisterMonitorImpl (&TheSCMonitor );
sl@0
   135
		return KErrNone;
sl@0
   136
		}
sl@0
   137
	else if (aReason==KModuleEntryReasonExtensionInit0 )
sl@0
   138
		{
sl@0
   139
		return KErrNone;
sl@0
   140
		}
sl@0
   141
	else if (aReason==KModuleEntryReasonExtensionInit1 )
sl@0
   142
		{
sl@0
   143
		LOG_CONTEXT
sl@0
   144
		CLTRACE("Enqueing dfc to init crash flash for System Crash Monitor after all modules loaded");
sl@0
   145
		StartSecondaryDfc.Enque ( );
sl@0
   146
		return KErrNone;
sl@0
   147
		}
sl@0
   148
	return KErrArgument;
sl@0
   149
	}
sl@0
   150
sl@0
   151
/**
sl@0
   152
 Method to intialize the system crash monitor
sl@0
   153
 @param aCategory the fault category type
sl@0
   154
 @param aReason the reason for crash
sl@0
   155
 @return restart type
sl@0
   156
 */
sl@0
   157
TInt SCMonitor::Init2 (TAny* aCategory, TInt aReason )
sl@0
   158
	{
sl@0
   159
	LOG_CONTEXT
sl@0
   160
	__KTRACE_OPT(KALWAYS, Kern::Printf("\n\nSystem Crash Monitor Launched: To Analyse Crash Produced Use Core Dump Server\n"));
sl@0
   161
sl@0
   162
	//Start logging the data:	
sl@0
   163
	//Need to lock kernel to access object containers (it technically is anyway, but flag isnt set)
sl@0
   164
	NKern::Lock();
sl@0
   165
	DoCrash(aCategory, aReason);	
sl@0
   166
	NKern::Unlock();		
sl@0
   167
		
sl@0
   168
	__KTRACE_OPT(KALWAYS, Kern::Printf("System Crash Monitor Finished: Log Size = [%d]\n", iDataSave->iCrashInf.iLogSize));
sl@0
   169
	
sl@0
   170
	return KRestartType;
sl@0
   171
	}
sl@0
   172
sl@0
   173
/**
sl@0
   174
 * This is responsible for setting up any structures required for processing of the crash
sl@0
   175
 * @param aCategory the fault category type
sl@0
   176
 * @param aReason 
sl@0
   177
 */
sl@0
   178
void SCMonitor::DoCrash(TAny* aCategory, TInt aReason )
sl@0
   179
	{
sl@0
   180
	// get debug mask
sl@0
   181
	TInt dbgMask = Kern::SuperPage().iDebugMask[0];
sl@0
   182
	
sl@0
   183
	// if we are writing to the comm port then we need to turn off other debug messages
sl@0
   184
	if( iDataSave->GetWriteSelect() == SCMDataSave::EWriteComm)
sl@0
   185
		{
sl@0
   186
		Kern::SuperPage().iDebugMask[0] = 0;
sl@0
   187
		}
sl@0
   188
	
sl@0
   189
	if(!aCategory)
sl@0
   190
		{
sl@0
   191
		CLTRACE("\tNULL category retrieved and returning");
sl@0
   192
		TheSCMonitor.iFlash->EndTransaction();
sl@0
   193
		return;
sl@0
   194
		}
sl@0
   195
sl@0
   196
	iFrame = NULL;
sl@0
   197
	
sl@0
   198
	CLTRACE("\tAbout to set category -- note: can occasionaly crash board");	
sl@0
   199
	iFaultCategory = *(const TDesC8*)aCategory;  // this crashes the board sometimes		
sl@0
   200
	iFaultReason = aReason;
sl@0
   201
	Epoc::SetMonitorExceptionHandler ((TLinAddr)HandleException );
sl@0
   202
	
sl@0
   203
	// get the first start block
sl@0
   204
	// will retieve start of flash by default
sl@0
   205
	SCMCrashBlockEntry block;
sl@0
   206
	TInt err = GetNextCrashStartPoint(block);  // will also attempt to read iScmConfig
sl@0
   207
sl@0
   208
	if(KErrNone == err)
sl@0
   209
		{
sl@0
   210
		CLTRACE2("SCMonitor::DoCrash next crash will be written at blocknumber = %d offset  %d"
sl@0
   211
				, block.iBlockNumber, block.iBlockOffset);
sl@0
   212
		}
sl@0
   213
	else
sl@0
   214
		{
sl@0
   215
		CLTRACE1("SCMonitor::DoCrash Failed to find a valid block to write to, can not continue. err = [%d]", err);
sl@0
   216
		return;
sl@0
   217
		}
sl@0
   218
	
sl@0
   219
	TUint crashId = block.iBlockNumber;	
sl@0
   220
	iDataSave->iWriter->ResetBytesWritten();		
sl@0
   221
	
sl@0
   222
	//Write the crash (1st pass is to gather header data)
sl@0
   223
	TInt spaceRequired = ProcessCrash(block, crashId, EFalse);					
sl@0
   224
	
sl@0
   225
	// now do the real write	
sl@0
   226
	// prepare flash for data	
sl@0
   227
	TheSCMonitor.iFlash->StartTransaction();	
sl@0
   228
	TheSCMonitor.iFlash->SetWritePos(block.iBlockOffset);
sl@0
   229
sl@0
   230
	//write the crash this time
sl@0
   231
	ProcessCrash(block, crashId, ETrue);
sl@0
   232
	
sl@0
   233
	TheSCMonitor.iFlash->EndTransaction();	
sl@0
   234
	
sl@0
   235
	// restore debug mask
sl@0
   236
	Kern::SuperPage().iDebugMask[0] = dbgMask;
sl@0
   237
	}
sl@0
   238
sl@0
   239
sl@0
   240
/**
sl@0
   241
 * This walks the existing crash log and finds out where current crashes finish
sl@0
   242
 * @param aBlockEntry Block to use. Only valid if KErrNone is returned.
sl@0
   243
 * @return One of the OS wide codes
sl@0
   244
 */
sl@0
   245
TInt SCMonitor::GetNextCrashStartPoint(SCMCrashBlockEntry& aBlockEntry)
sl@0
   246
	{
sl@0
   247
	LOG_CONTEXT	
sl@0
   248
	
sl@0
   249
	//First thing is to try and read the config
sl@0
   250
	TBool configFound = (iDataSave->ReadConfig(*iScmConfig) == KErrNone);
sl@0
   251
	
sl@0
   252
	if( iMultiCrashInfo)	
sl@0
   253
		{				
sl@0
   254
		/**
sl@0
   255
		 * data save has been configured to use multicrash info to find the next block we are on we need to scan each
sl@0
   256
		 * block to see if it contains a valid header. if we find an empty block in our block list then that is the
sl@0
   257
		 * one we will use if we find no empty blocks then we have no room left	
sl@0
   258
		 */
sl@0
   259
		iMultiCrashInfo->Reset();
sl@0
   260
		SCMCrashBlockEntry* block = iMultiCrashInfo->GetNextBlock();
sl@0
   261
		TBool blockFound = EFalse;				
sl@0
   262
		
sl@0
   263
		//For any crashes in flash, we need to record where they end, so that we can then go to the next
sl@0
   264
		//block after the one in which it ends
sl@0
   265
		TInt crashEndPoint = 0;		
sl@0
   266
		
sl@0
   267
		while(block)
sl@0
   268
			{	
sl@0
   269
			CLTRACE1("SCMonitor::GetNextCrashStartPoint Processing block number %d", block->iBlockNumber );			
sl@0
   270
			
sl@0
   271
			//If we have already found our block, we should erase subsequent ones for use
sl@0
   272
			if(blockFound)
sl@0
   273
				{
sl@0
   274
				TInt err = EraseFlashBlock(*block);
sl@0
   275
				if(err != KErrNone)
sl@0
   276
					{					
sl@0
   277
					return err;
sl@0
   278
					}
sl@0
   279
				
sl@0
   280
				block = iMultiCrashInfo->GetNextBlock(); 
sl@0
   281
				continue;
sl@0
   282
				}	
sl@0
   283
			
sl@0
   284
			//is this block before a crash end? if it is, we cant use it as a crash can span multiple blocks
sl@0
   285
			if(block->iBlockOffset >= crashEndPoint)
sl@0
   286
				{
sl@0
   287
				//special condition if we have a config
sl@0
   288
				TUint startPos = block->iBlockOffset;
sl@0
   289
				TUint skipBytes = 0;
sl@0
   290
				if(configFound && block->iBlockOffset == 0)
sl@0
   291
					{
sl@0
   292
					startPos+=iScmConfig->GetSize();
sl@0
   293
					
sl@0
   294
					//must align to flash for read
sl@0
   295
					skipBytes = startPos % KFlashAlignment;	
sl@0
   296
					startPos -= skipBytes;
sl@0
   297
					}
sl@0
   298
				
sl@0
   299
				// try and read an info header at these flash coords
sl@0
   300
				TBuf8<TCrashInfoHeader::KSCMCrashInfoMaxSize + KFlashAlignment> buf;
sl@0
   301
				buf.SetLength(TCrashInfoHeader::KSCMCrashInfoMaxSize + KFlashAlignment);
sl@0
   302
	
sl@0
   303
				CLTRACE1("(SCMonitor::GetNextCrashStartPoint) reading at offset %d", block->iBlockOffset);
sl@0
   304
				
sl@0
   305
				TheSCMonitor.iFlash->SetReadPos(startPos);
sl@0
   306
				TheSCMonitor.iFlash->Read(buf);
sl@0
   307
				
sl@0
   308
				// create the buffer applying the offset of bytes skipped
sl@0
   309
				TByteStreamReader reader(const_cast<TUint8*> (buf.Ptr() + skipBytes));
sl@0
   310
				
sl@0
   311
				TCrashInfoHeader header;								
sl@0
   312
				TInt err = header.Deserialize(reader);
sl@0
   313
				
sl@0
   314
				if(err == KErrCorrupt)
sl@0
   315
					{
sl@0
   316
					CLTRACE2("(SCMonitor::GetNextCrashStartPoint) Found empty block blocknumber %d blockoffset = %d"
sl@0
   317
							, block->iBlockNumber, block->iBlockOffset);
sl@0
   318
										
sl@0
   319
					blockFound = ETrue;
sl@0
   320
					aBlockEntry = *block;
sl@0
   321
					
sl@0
   322
					continue; //Dont get next block, as next run will erase this current block for use
sl@0
   323
					}
sl@0
   324
				else
sl@0
   325
					{					
sl@0
   326
					crashEndPoint = header.iLogSize + startPos;
sl@0
   327
					CLTRACE3("(SCMonitor::GetNextCrashStartPoint) In block [%d] we found a valid crash header. This crash finishes at [%d] [0x%X]", block->iBlockNumber, crashEndPoint, crashEndPoint);
sl@0
   328
					}
sl@0
   329
				}
sl@0
   330
			
sl@0
   331
			block = iMultiCrashInfo->GetNextBlock();
sl@0
   332
			}									
sl@0
   333
			
sl@0
   334
		if(blockFound)
sl@0
   335
			{
sl@0
   336
			return KErrNone;
sl@0
   337
			}
sl@0
   338
		else
sl@0
   339
			{
sl@0
   340
			//CLTRACE("(SCMonitor::GetNextCrashStartPoint) No available blocks TREATING as NO MULTICRASH INFO will write to default block");
sl@0
   341
			//In this case should we just overwrite old crashes and return the first block as the comment above suggests
sl@0
   342
			//return blockFound;
sl@0
   343
			}
sl@0
   344
		}
sl@0
   345
sl@0
   346
	// no multi crash info supplied - use default first block settings
sl@0
   347
	TInt err = EraseEntireFlashPartition();
sl@0
   348
	if(err != KErrNone)
sl@0
   349
		{
sl@0
   350
		CLTRACE1("Unable to delete area required to log to flash. Aborting. Error - [%d]", err);
sl@0
   351
		return err;
sl@0
   352
		}
sl@0
   353
	
sl@0
   354
	aBlockEntry = SCMCrashBlockEntry(0,0,0);
sl@0
   355
	return KErrNone;
sl@0
   356
	}
sl@0
   357
sl@0
   358
/**
sl@0
   359
 * Handles the processing of the crash
sl@0
   360
 * @return The size of the crash log (including header) that has been/will be written
sl@0
   361
 */
sl@0
   362
TInt SCMonitor::ProcessCrash(const SCMCrashBlockEntry& aBlock, TUint aCrashId, TBool aCommit)
sl@0
   363
	{	
sl@0
   364
	LOG_CONTEXT
sl@0
   365
	CLTRACE5("aBlock.iBlockOffset = [%d]  [0x%X] aBlock.iBlockNumber = %d aBlock.iBlockSize = [%d]  [0x%X]",
sl@0
   366
			aBlock.iBlockOffset, aBlock.iBlockOffset, aBlock.iBlockNumber, aBlock.iBlockSize, aBlock.iBlockSize);		
sl@0
   367
	
sl@0
   368
	// reset writer for start of each crash
sl@0
   369
	iDataSave->iWriter->ResetBytesWritten();
sl@0
   370
	TInt logLevel = 0;
sl@0
   371
sl@0
   372
	if(aCommit)
sl@0
   373
		{
sl@0
   374
		logLevel = KALWAYS;
sl@0
   375
		iDataSave->iWriter->EnablePhysicalWriting();	
sl@0
   376
		}
sl@0
   377
	else
sl@0
   378
		{
sl@0
   379
#if defined(_DEBUG)
sl@0
   380
		logLevel = KDEBUGGER;
sl@0
   381
#else
sl@0
   382
		logLevel = KALWAYS; //Doesnt matter, KTRACE OPT is empty for rel builds 
sl@0
   383
		if(logLevel != KALWAYS)
sl@0
   384
			{
sl@0
   385
			//This is to avoid warning
sl@0
   386
			}
sl@0
   387
#endif
sl@0
   388
		
sl@0
   389
		iDataSave->iWriter->DisablePhysicalWriting();	
sl@0
   390
		}
sl@0
   391
	
sl@0
   392
	iDataSave->SetByteCount(aBlock.iBlockOffset);	
sl@0
   393
	if(aBlock.iBlockOffset == 0 && aBlock.iBlockNumber == 0)
sl@0
   394
		{	
sl@0
   395
		// this is the first crash - we need to save the config here first
sl@0
   396
		CLTRACE("(SCMonitor::ProcessCrash) - this is block 0 - WRITING CONFIG");
sl@0
   397
		iDataSave->LogConfig(*iScmConfig);	
sl@0
   398
		
sl@0
   399
		//Config is not part of crash so reset bytes written			
sl@0
   400
		iDataSave->SetCrashStartingPoint(iDataSave->iWriter->GetBytesWritten());		
sl@0
   401
		}	
sl@0
   402
	else
sl@0
   403
		{
sl@0
   404
		iDataSave->SetCrashStartingPoint(aBlock.iBlockOffset);
sl@0
   405
		}	
sl@0
   406
	
sl@0
   407
	iDataSave->iWriter->ResetBytesWritten();
sl@0
   408
	
sl@0
   409
	TUint32 logSize = 0;
sl@0
   410
	TUint sizeOfObjectDumped = 0;
sl@0
   411
		
sl@0
   412
	TInt err = iDataSave->LogCrashHeader(iFaultCategory, iFaultReason, aCrashId, sizeOfObjectDumped);		
sl@0
   413
	if(KErrNone != err)
sl@0
   414
		{
sl@0
   415
		CLTRACE("System Crash Monitor: Failed to create crash info header - (TCrashInfo)"); 
sl@0
   416
		return KRestartType;
sl@0
   417
		}	
sl@0
   418
	
sl@0
   419
	logSize += sizeOfObjectDumped;
sl@0
   420
	
sl@0
   421
	//Now we must read the configuration to use. This is held at the start of our flash partition
sl@0
   422
	//and managed by the iConfig object
sl@0
   423
	iScmConfig->ResetToHighestPriority();	
sl@0
   424
		
sl@0
   425
	//Always want the crash context
sl@0
   426
	iDataSave->iHdr.iCTFullRegOffset = logSize + iDataSave->GetCrashStartingPoint();
sl@0
   427
	
sl@0
   428
	err = iDataSave->LogCPURegisters(sizeOfObjectDumped);
sl@0
   429
	if(KErrNone != err)
sl@0
   430
		{
sl@0
   431
		CLTRACE1("\tError logging full registers = %d", err);
sl@0
   432
		}	
sl@0
   433
	
sl@0
   434
	logSize += sizeOfObjectDumped;
sl@0
   435
	
sl@0
   436
	CLTRACE("\tAbout to enter processing loop");		
sl@0
   437
	SCMDataSave::TDataToDump dump;
sl@0
   438
		
sl@0
   439
	for(;;)		
sl@0
   440
		{		
sl@0
   441
		//now we get each item by priority from the configuration
sl@0
   442
		TConfigItem* configItem = iScmConfig->GetNextItem();
sl@0
   443
sl@0
   444
		if(!configItem)
sl@0
   445
			{
sl@0
   446
			// end of list
sl@0
   447
			break;
sl@0
   448
			}
sl@0
   449
		
sl@0
   450
		CLTRACE1("\nLooking at item type [%d]", configItem->GetDataType());
sl@0
   451
		if(configItem->GetSpaceRequired() > iDataSave->SpaceRemaining())
sl@0
   452
			{
sl@0
   453
			__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()));
sl@0
   454
			continue;
sl@0
   455
			}
sl@0
   456
		else
sl@0
   457
			{
sl@0
   458
			CLTRACE1("Will require [%d] bytes for this item", configItem->GetSpaceRequired());
sl@0
   459
			}
sl@0
   460
		
sl@0
   461
		// only interested in logging items with priority > 0
sl@0
   462
		if( configItem->GetPriority() <= 0)
sl@0
   463
			{
sl@0
   464
			CLTRACE1("\tIgnored config item type %d priority 0", configItem->GetDataType());
sl@0
   465
			continue;
sl@0
   466
			}
sl@0
   467
			
sl@0
   468
		//there are a lot of TUints in the hdr to record where we wrote this item. 
sl@0
   469
		//This will point to the one of interest for this configItem
sl@0
   470
		TUint32* offsetPointer = NULL;				
sl@0
   471
		
sl@0
   472
		//now we check the type of data we wish to dump
sl@0
   473
		switch(configItem->GetDataType())
sl@0
   474
			{
sl@0
   475
			case TConfigItem::ECrashedThreadMetaData:			
sl@0
   476
				{
sl@0
   477
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedThreadMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   478
				
sl@0
   479
				err = LogThreadMetaData(SCMDataSave::EThreadSpecific, sizeOfObjectDumped);
sl@0
   480
				offsetPointer = &(iDataSave->iHdr.iCTMetaOffset);
sl@0
   481
				
sl@0
   482
				break;
sl@0
   483
				}
sl@0
   484
			case TConfigItem::EThreadsMetaData:			
sl@0
   485
				{
sl@0
   486
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   487
				
sl@0
   488
				//record location we are writing to in the header
sl@0
   489
				iDataSave->iHdr.iTLstOffset = iDataSave->iWriter->GetBytesWritten();
sl@0
   490
				err = LogThreadMetaData(SCMDataSave::ESystemWide, sizeOfObjectDumped);
sl@0
   491
				offsetPointer = &(iDataSave->iHdr.iTLstOffset);
sl@0
   492
				
sl@0
   493
				break;
sl@0
   494
				}
sl@0
   495
			case TConfigItem::ECrashedProcessMetaData:			
sl@0
   496
				{
sl@0
   497
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   498
					
sl@0
   499
				err = LogProcessMetaData(SCMDataSave::EProcessSpecific, sizeOfObjectDumped);
sl@0
   500
				offsetPointer = &(iDataSave->iHdr.iCPMetaOffset);
sl@0
   501
				
sl@0
   502
				break;
sl@0
   503
				}
sl@0
   504
			case TConfigItem::EProcessMetaData:		
sl@0
   505
				{
sl@0
   506
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EProcessMetaData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   507
								
sl@0
   508
				err = LogProcessMetaData(SCMDataSave::ESystemWide, sizeOfObjectDumped);
sl@0
   509
				offsetPointer = &(iDataSave->iHdr.iPLstOffset);
sl@0
   510
				
sl@0
   511
				break;
sl@0
   512
				}
sl@0
   513
			case TConfigItem::ECrashedProcessUsrStacks:			
sl@0
   514
				{
sl@0
   515
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessUsrStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   516
								
sl@0
   517
				//define what we wish to dump
sl@0
   518
				dump.iMetaData = EFalse;
sl@0
   519
				dump.iCodeSegs = EFalse;
sl@0
   520
				dump.iStk = SCMDataSave::EUsrStack;
sl@0
   521
				dump.iReg = SCMDataSave::ERegSetNone;	
sl@0
   522
				err = LogObjectContainers(EThread, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);	
sl@0
   523
				offsetPointer = &(iDataSave->iHdr.iCTUsrStkOffset);
sl@0
   524
				
sl@0
   525
				break;
sl@0
   526
				}
sl@0
   527
			case TConfigItem::EThreadsUsrStack:			
sl@0
   528
				{
sl@0
   529
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsUsrStack at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   530
				
sl@0
   531
				//define what we wish to dump
sl@0
   532
				dump.iMetaData = EFalse;
sl@0
   533
				dump.iCodeSegs = EFalse;
sl@0
   534
				dump.iStk = SCMDataSave::EUsrStack;
sl@0
   535
				dump.iReg = SCMDataSave::ERegSetNone;
sl@0
   536
sl@0
   537
				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
sl@0
   538
				offsetPointer = &(iDataSave->iHdr.iSysSvrStkOffset);
sl@0
   539
				
sl@0
   540
				break;
sl@0
   541
				}
sl@0
   542
			case TConfigItem::ECrashedProcessSvrStacks:			
sl@0
   543
				{
sl@0
   544
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessSvrStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   545
								
sl@0
   546
				//define what we wish to dump
sl@0
   547
				dump.iMetaData = EFalse;
sl@0
   548
				dump.iCodeSegs = EFalse;
sl@0
   549
				dump.iStk = SCMDataSave::ESvrStack;
sl@0
   550
				dump.iReg = SCMDataSave::ERegSetNone;
sl@0
   551
				
sl@0
   552
				err = LogObjectContainers(EThread, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);
sl@0
   553
				offsetPointer = &(iDataSave->iHdr.iCTSvrStkOffset);
sl@0
   554
				
sl@0
   555
				break;
sl@0
   556
				}
sl@0
   557
			case TConfigItem::EThreadsSvrStack:			
sl@0
   558
				{
sl@0
   559
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsSvrStack at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   560
								
sl@0
   561
				//define what we wish to dump
sl@0
   562
				dump.iMetaData = EFalse;
sl@0
   563
				dump.iCodeSegs = EFalse;
sl@0
   564
				dump.iStk = SCMDataSave::ESvrStack;
sl@0
   565
				dump.iReg = SCMDataSave::ERegSetNone;
sl@0
   566
				
sl@0
   567
				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
sl@0
   568
				offsetPointer = &(iDataSave->iHdr.iSysSvrStkOffset);
sl@0
   569
				
sl@0
   570
				break;
sl@0
   571
				}
sl@0
   572
			case TConfigItem::EThreadsUsrRegisters:		
sl@0
   573
				{
sl@0
   574
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsUsrRegisters at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   575
								
sl@0
   576
				//define what we wish to dump
sl@0
   577
				dump.iMetaData = EFalse;
sl@0
   578
				dump.iCodeSegs = EFalse;
sl@0
   579
				dump.iStk = SCMDataSave::EStackTypeNone;
sl@0
   580
				dump.iReg = SCMDataSave::EUserRegisters;
sl@0
   581
				
sl@0
   582
				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
sl@0
   583
				offsetPointer = &(iDataSave->iHdr.iSysUsrRegOffset);
sl@0
   584
				
sl@0
   585
				break;
sl@0
   586
				}
sl@0
   587
			case TConfigItem::EThreadsSvrRegisters:		
sl@0
   588
				{
sl@0
   589
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EThreadsSvrRegisters at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   590
								
sl@0
   591
				//define what we wish to dump
sl@0
   592
				dump.iMetaData = EFalse;
sl@0
   593
				dump.iCodeSegs = EFalse;
sl@0
   594
				dump.iStk = SCMDataSave::EStackTypeNone;
sl@0
   595
				dump.iReg = SCMDataSave::ESupervisorRegisters;
sl@0
   596
				
sl@0
   597
				err = LogObjectContainers(EThread, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
sl@0
   598
				offsetPointer = &(iDataSave->iHdr.iSysSvrRegOffset);
sl@0
   599
				
sl@0
   600
				break;
sl@0
   601
				}
sl@0
   602
			case TConfigItem::EExceptionStacks:
sl@0
   603
				{
sl@0
   604
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EExceptionStacks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   605
							
sl@0
   606
				err = iDataSave->LogExceptionStacks(sizeOfObjectDumped);
sl@0
   607
				offsetPointer = &(iDataSave->iHdr.iExcStkOffset);
sl@0
   608
				
sl@0
   609
				break;
sl@0
   610
				}
sl@0
   611
			case TConfigItem::ECrashedProcessCodeSegs:
sl@0
   612
				{	
sl@0
   613
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ECrashedProcessCodeSegs at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   614
								
sl@0
   615
				//define what we wish to dump
sl@0
   616
				dump.iMetaData = EFalse;
sl@0
   617
				dump.iCodeSegs = ETrue;
sl@0
   618
				dump.iStk = SCMDataSave::EStackTypeNone;
sl@0
   619
				dump.iReg = SCMDataSave::ERegSetNone;				
sl@0
   620
				
sl@0
   621
				err = LogObjectContainers(EProcess, SCMDataSave::EProcessSpecific, dump, sizeOfObjectDumped);
sl@0
   622
				offsetPointer = &(iDataSave->iHdr.iCPCodeSegOffset);
sl@0
   623
				
sl@0
   624
				break;
sl@0
   625
				}
sl@0
   626
			case TConfigItem::EProcessCodeSegs:
sl@0
   627
				{
sl@0
   628
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EProcessCodeSegs at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   629
								
sl@0
   630
				//define what we wish to dump
sl@0
   631
				dump.iMetaData = EFalse;
sl@0
   632
				dump.iCodeSegs = ETrue;
sl@0
   633
				dump.iStk = SCMDataSave::EStackTypeNone;
sl@0
   634
				dump.iReg = SCMDataSave::ERegSetNone;
sl@0
   635
				err = LogObjectContainers(EProcess, SCMDataSave::ESystemWide, dump, sizeOfObjectDumped);
sl@0
   636
				offsetPointer = &(iDataSave->iHdr.iSysCodeSegOffset);
sl@0
   637
				
sl@0
   638
				break;
sl@0
   639
				}
sl@0
   640
			case TConfigItem::ETraceData:
sl@0
   641
				{
sl@0
   642
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ETraceData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   643
									
sl@0
   644
				err = iDataSave->LogTraceBuffer(configItem->GetSizeToDump(), sizeOfObjectDumped);
sl@0
   645
				offsetPointer = &(iDataSave->iHdr.iTraceOffset);
sl@0
   646
				
sl@0
   647
				break;
sl@0
   648
				}		
sl@0
   649
			case TConfigItem::ELocks:
sl@0
   650
				{
sl@0
   651
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ELocks at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));	
sl@0
   652
					
sl@0
   653
				err = iDataSave->LogLocks(sizeOfObjectDumped);
sl@0
   654
				offsetPointer = &(iDataSave->iHdr.iScmLocksOffset);
sl@0
   655
				
sl@0
   656
				break;
sl@0
   657
				}
sl@0
   658
			case TConfigItem::EKernelHeap:
sl@0
   659
				{
sl@0
   660
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EKernelHeap at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   661
				
sl@0
   662
				err = iDataSave->LogKernelHeap(sizeOfObjectDumped);
sl@0
   663
				offsetPointer = &(iDataSave->iHdr.iKernelHeapOffset);
sl@0
   664
				
sl@0
   665
				break;
sl@0
   666
				}
sl@0
   667
			case TConfigItem::EVariantSpecificData:
sl@0
   668
				{
sl@0
   669
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: EVariantSpecificData at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   670
				
sl@0
   671
				err = iDataSave->LogVariantSpecificData(sizeOfObjectDumped);
sl@0
   672
				offsetPointer = &(iDataSave->iHdr.iVarSpecInfOffset);
sl@0
   673
				
sl@0
   674
				break;
sl@0
   675
				}
sl@0
   676
			case TConfigItem::ERomInfo:
sl@0
   677
				{
sl@0
   678
				__KTRACE_OPT(logLevel, Kern::Printf("\tDoing: ERomInfo at [%d] offset from [%d]", iDataSave->iWriter->GetBytesWritten(), iDataSave->GetCrashStartingPoint()));
sl@0
   679
				
sl@0
   680
				err = iDataSave->LogRomInfo(sizeOfObjectDumped);
sl@0
   681
				offsetPointer = &(iDataSave->iHdr.iRomInfoOffset);
sl@0
   682
				
sl@0
   683
				break;
sl@0
   684
				}
sl@0
   685
			//unknown configuration type - something bad is going on
sl@0
   686
			default: return 0;			
sl@0
   687
			}				
sl@0
   688
		
sl@0
   689
		if(KErrNone != err)
sl@0
   690
			{
sl@0
   691
			__KTRACE_OPT(logLevel, Kern::Printf("\tError logging data: [%d]   Type = [%d]", err, aBlock.iBlockOffset));
sl@0
   692
			continue;
sl@0
   693
			}
sl@0
   694
		
sl@0
   695
		//Set the space required so next time around we will know in advance how much space we need
sl@0
   696
		configItem->SetSpaceRequired(sizeOfObjectDumped);		
sl@0
   697
		
sl@0
   698
		//Note: the following steps are only required for the first time we call process crash. The second time,
sl@0
   699
		//when physical writing is enabled, these will have been written already and so they dont matter
sl@0
   700
		
sl@0
   701
		//update the offset and logsize if we are going to dump this item
sl@0
   702
		TUint32 absoluteLogPos = logSize + iDataSave->GetCrashStartingPoint();
sl@0
   703
		if(absoluteLogPos+sizeOfObjectDumped < iDataSave->MaxLogSize())
sl@0
   704
			{
sl@0
   705
			//now, we must record where in the crash log this item will be dumped
sl@0
   706
			*offsetPointer = absoluteLogPos;
sl@0
   707
			logSize += sizeOfObjectDumped;
sl@0
   708
			}
sl@0
   709
		}
sl@0
   710
	
sl@0
   711
	iDataSave->iCrashInf.iLogSize = logSize;	
sl@0
   712
	iDataSave->iWriter->FlushCache();		
sl@0
   713
	
sl@0
   714
	return iDataSave->iCrashInf.iLogSize;
sl@0
   715
	}
sl@0
   716
sl@0
   717
/**
sl@0
   718
 * Logs the meta data for processes
sl@0
   719
 * @param aCurrentProcess - scope to dump
sl@0
   720
 * @return one of the OS wide codes
sl@0
   721
 */
sl@0
   722
TInt SCMonitor::LogProcessMetaData(SCMDataSave::TDumpScope aScope, TUint& aSizeDumped) const
sl@0
   723
	{
sl@0
   724
	LOG_CONTEXT
sl@0
   725
	
sl@0
   726
	SCMDataSave::TDataToDump dump;
sl@0
   727
	dump.iMetaData = ETrue;
sl@0
   728
	
sl@0
   729
	return LogObjectContainers(EProcess, aScope, dump, aSizeDumped);
sl@0
   730
	}
sl@0
   731
sl@0
   732
/**
sl@0
   733
 * 
sl@0
   734
 * @param aCurrentThread -  to only do the current (crashed thread) or to do all the others
sl@0
   735
 * @return one of the OS wide codes
sl@0
   736
 */
sl@0
   737
TInt SCMonitor::LogThreadMetaData(SCMDataSave::TDumpScope aScope, TUint& aSizeDumped) const
sl@0
   738
	{
sl@0
   739
	LOG_CONTEXT
sl@0
   740
	
sl@0
   741
	SCMDataSave::TDataToDump dump; 
sl@0
   742
	dump.iMetaData = ETrue;
sl@0
   743
	
sl@0
   744
	return LogObjectContainers(EThread, aScope, dump, aSizeDumped);
sl@0
   745
	}
sl@0
   746
sl@0
   747
/**
sl@0
   748
 * Generic method that looks at all kernel objects of aObjectType
sl@0
   749
 * @param aObjectType
sl@0
   750
 * @param aDumpScope - if you wish to dump for the the current process, current thread or entire system
sl@0
   751
 * @param aDataToDump - data you wish to dump
sl@0
   752
 * @param aSizeDumped - records how much was dumped
sl@0
   753
 * @return
sl@0
   754
 */
sl@0
   755
TInt SCMonitor::LogObjectContainers(TObjectType aObjectType, SCMDataSave::TDumpScope aDumpScope, const SCMDataSave::TDataToDump& aDataToDump, TUint& aSizeDumped) const
sl@0
   756
	{
sl@0
   757
	aSizeDumped = 0;
sl@0
   758
	
sl@0
   759
	if(aObjectType >= ENumObjectTypes)
sl@0
   760
		{
sl@0
   761
		return KErrArgument;
sl@0
   762
		}
sl@0
   763
	
sl@0
   764
	//Get the object container for the given object type
sl@0
   765
	DObjectCon* objectContainer = Kern::Containers()[aObjectType];
sl@0
   766
	if(objectContainer == NULL)
sl@0
   767
		{		
sl@0
   768
		CLTRACE("tFailed to get object container");
sl@0
   769
		return KErrNotFound;
sl@0
   770
		}
sl@0
   771
	
sl@0
   772
	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
sl@0
   773
	if(objectContainer->iMutex->iHoldCount)
sl@0
   774
		{
sl@0
   775
		CLTRACE("\tObject Container is in an inconsistant state");
sl@0
   776
		return KErrCorrupt;
sl@0
   777
		}
sl@0
   778
	
sl@0
   779
	TInt numObjects = objectContainer->Count();
sl@0
   780
	TInt err = KErrNone;	
sl@0
   781
	
sl@0
   782
	for(TInt cnt = 0; cnt< numObjects; cnt ++)
sl@0
   783
		{	
sl@0
   784
		DObject* object = (*objectContainer)[cnt];
sl@0
   785
		
sl@0
   786
		//Are we interested in the object? scope only relevant for thread and process objects, for others, the scope is implicit
sl@0
   787
		if(aObjectType == EThread)			
sl@0
   788
			{
sl@0
   789
			switch(aDumpScope)
sl@0
   790
				{
sl@0
   791
				case SCMDataSave::EThreadSpecific :
sl@0
   792
					{
sl@0
   793
					//if we are interested in the current thread and this is not it, continue
sl@0
   794
					if(((DThread*)object) != &Kern::CurrentThread())
sl@0
   795
						continue;
sl@0
   796
					break;
sl@0
   797
					}
sl@0
   798
				case SCMDataSave::EProcessSpecific :
sl@0
   799
					{
sl@0
   800
					//if we are interested in the current proc and this is not it, continue
sl@0
   801
					if(((DThread*)object)->iOwningProcess != &Kern::CurrentProcess())
sl@0
   802
						continue;					
sl@0
   803
					break;
sl@0
   804
					}
sl@0
   805
				case SCMDataSave::ESystemWide :
sl@0
   806
				default: 
sl@0
   807
					break;
sl@0
   808
				}
sl@0
   809
			}
sl@0
   810
		else if(aObjectType == EProcess)
sl@0
   811
			{
sl@0
   812
			switch(aDumpScope)
sl@0
   813
				{
sl@0
   814
				case SCMDataSave::EProcessSpecific :
sl@0
   815
					{
sl@0
   816
					if((DProcess*)object != &Kern::CurrentProcess())
sl@0
   817
						continue;
sl@0
   818
					break;
sl@0
   819
					}
sl@0
   820
				case SCMDataSave::EThreadSpecific :  //thread specific process doesnt make sense
sl@0
   821
					return KErrArgument;				
sl@0
   822
				case SCMDataSave::ESystemWide :
sl@0
   823
				default:
sl@0
   824
					break;
sl@0
   825
				}
sl@0
   826
			}
sl@0
   827
		
sl@0
   828
		//Now we look at the data we have been asked to dump
sl@0
   829
		if(aDataToDump.iMetaData)
sl@0
   830
			{
sl@0
   831
			TUint dumped = 0;
sl@0
   832
			err = HelpDumpMetaData(object, aObjectType, dumped);
sl@0
   833
			if(KErrNone != err)
sl@0
   834
				{
sl@0
   835
				CLTRACE1("Failed to meta data: [%d]", err);
sl@0
   836
				return err;
sl@0
   837
				}
sl@0
   838
			aSizeDumped += dumped;
sl@0
   839
			}
sl@0
   840
		
sl@0
   841
		if(aDataToDump.iCodeSegs)
sl@0
   842
			{
sl@0
   843
			if(aObjectType != EProcess)
sl@0
   844
				{
sl@0
   845
				return KErrArgument;
sl@0
   846
				}
sl@0
   847
			
sl@0
   848
			TUint dumped = 0;
sl@0
   849
			err = iDataSave->LogCodeSegments((DProcess*)object, dumped);
sl@0
   850
			if(KErrNone != err)
sl@0
   851
				{
sl@0
   852
				CLTRACE1("Failed to log code segments: [%d]", err);
sl@0
   853
				return err;
sl@0
   854
				}
sl@0
   855
			aSizeDumped += dumped;
sl@0
   856
			}
sl@0
   857
		
sl@0
   858
		if(aDataToDump.iStk != SCMDataSave::EStackTypeNone)
sl@0
   859
			{
sl@0
   860
			TUint dumped = 0;
sl@0
   861
			err = HelpDumpStacks(object, aObjectType, dumped, aDataToDump.iStk);
sl@0
   862
			if(KErrNone != err)
sl@0
   863
				{
sl@0
   864
				CLTRACE1("Failed to log stacks: [%d]", err);
sl@0
   865
				return err;
sl@0
   866
				}
sl@0
   867
			aSizeDumped += dumped;
sl@0
   868
			}
sl@0
   869
		
sl@0
   870
		if(aDataToDump.iReg != SCMDataSave::ERegSetNone)
sl@0
   871
			{			
sl@0
   872
			if(aObjectType != EThread)
sl@0
   873
				{
sl@0
   874
				return KErrArgument;
sl@0
   875
				}
sl@0
   876
			TUint dumped = 0;
sl@0
   877
			err = iDataSave->LogRegisters((DThread*)object, aDataToDump.iReg, dumped);	
sl@0
   878
			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
sl@0
   879
				{
sl@0
   880
				CLTRACE1("Failed to log registers: [%d]", err);
sl@0
   881
				return err;
sl@0
   882
				}
sl@0
   883
			aSizeDumped += dumped;
sl@0
   884
			}
sl@0
   885
		}
sl@0
   886
	
sl@0
   887
	return KErrNone;
sl@0
   888
	}
sl@0
   889
sl@0
   890
/**
sl@0
   891
 * Helper method for dumping stacks. Looks to see what type of stack we want and then calls
sl@0
   892
 * appropriate method
sl@0
   893
 * @param aObject The DThread object whose stack we want
sl@0
   894
 * @param aObjectType The object type of this aObject. Anything other than EThread will give KErrArgument
sl@0
   895
 * @param aSizeDumped Holds the size of the stack dumped after processing 
sl@0
   896
 * @param aStkType The type of stack to be dumped
sl@0
   897
 * @see TObjectType
sl@0
   898
 * @see SCMDataSave::TStackType
sl@0
   899
 * @return One of the system wide codes
sl@0
   900
 */
sl@0
   901
TInt SCMonitor::HelpDumpStacks(DObject* aObject, TObjectType aObjectType, TUint& aSizeDumped, SCMDataSave::TStackType aStkType) const
sl@0
   902
	{
sl@0
   903
	//verify args
sl@0
   904
	if(aObjectType != EThread)
sl@0
   905
		{
sl@0
   906
		return KErrArgument;
sl@0
   907
		}
sl@0
   908
	
sl@0
   909
	switch(aStkType)
sl@0
   910
		{
sl@0
   911
		case SCMDataSave::EUsrStack:
sl@0
   912
			{
sl@0
   913
			return iDataSave->LogThreadUserStack((DThread*)aObject, ETrue, aSizeDumped);
sl@0
   914
			}
sl@0
   915
		case SCMDataSave::ESvrStack:
sl@0
   916
			{
sl@0
   917
			return iDataSave->LogThreadSupervisorStack((DThread*)aObject, ETrue, aSizeDumped);
sl@0
   918
			}
sl@0
   919
		default: return KErrArgument;
sl@0
   920
		}
sl@0
   921
	}
sl@0
   922
sl@0
   923
/**
sl@0
   924
 * Helper method to dump meta data about a DThread or a DProcess object
sl@0
   925
 * @param aObject DObject to use
sl@0
   926
 * @param aObjectType Type of DObject. Must be EThread or EProcess
sl@0
   927
 * @param aSizeDumped Holds the size of the stack dumped after processing 
sl@0
   928
 * @return
sl@0
   929
 */
sl@0
   930
TInt SCMonitor::HelpDumpMetaData(DObject* aObject, TObjectType aObjectType, TUint& aSizeDumped) const
sl@0
   931
	{
sl@0
   932
	aSizeDumped = 0;
sl@0
   933
	
sl@0
   934
	switch(aObjectType)
sl@0
   935
		{
sl@0
   936
		case EThread:
sl@0
   937
			{
sl@0
   938
			return iDataSave->LogThreadData((DThread*)aObject, aSizeDumped);	 
sl@0
   939
			}
sl@0
   940
		case EProcess:
sl@0
   941
			{
sl@0
   942
			return iDataSave->LogProcessData((DProcess*)aObject, aSizeDumped);
sl@0
   943
			}
sl@0
   944
		default: return KErrArgument;
sl@0
   945
		}
sl@0
   946
	}
sl@0
   947
sl@0
   948
/**
sl@0
   949
 * Wrapper method around the flash erase block fundtion to determine if the erase was succesful.
sl@0
   950
 * If the erase was not succesful we can't continue as we cannot write.
sl@0
   951
 * @param aBlockOffset Block to erase
sl@0
   952
 * @return One of the OS wide codes
sl@0
   953
 */
sl@0
   954
TInt SCMonitor::EraseFlashBlock(const SCMCrashBlockEntry& aBlock)
sl@0
   955
	{	
sl@0
   956
	iFlash->StartTransaction();
sl@0
   957
	
sl@0
   958
	TInt numAttempts = 0;
sl@0
   959
	while(numAttempts < KFlashEraseAttempts)
sl@0
   960
		{
sl@0
   961
		iFlash->SetWritePos(aBlock.iBlockOffset);
sl@0
   962
		iFlash->EraseFlashBlock(aBlock.iBlockOffset);
sl@0
   963
		
sl@0
   964
		//we will read the flash to make sure that it set the block to all 1's (well not all, just the start)
sl@0
   965
		TBuf8<sizeof(TUint32)> buf;
sl@0
   966
		buf.SetLength(sizeof(TUint32));
sl@0
   967
				
sl@0
   968
		iFlash->SetReadPos(aBlock.iBlockOffset);
sl@0
   969
		iFlash->Read(buf);
sl@0
   970
		
sl@0
   971
		volatile TUint32* result = (TUint32*)buf.Ptr();
sl@0
   972
		if(*result == 0xFFFFFFFF)
sl@0
   973
			{			
sl@0
   974
			__KTRACE_OPT(KALWAYS, Kern::Printf("Erase of block [0x%X] succesful after [%d] attempts", aBlock.iBlockOffset, numAttempts+1))			
sl@0
   975
			iFlash->EndTransaction();			
sl@0
   976
			return KErrNone;
sl@0
   977
			}
sl@0
   978
		
sl@0
   979
		numAttempts++;
sl@0
   980
		
sl@0
   981
		//Sometimes a write to the block helps the next erase
sl@0
   982
		TUint32 bytesWritten = 0;		
sl@0
   983
		while(bytesWritten < aBlock.iBlockSize)
sl@0
   984
			{
sl@0
   985
			TBuf8<sizeof(TUint8)> num;
sl@0
   986
			num.Append(0x0);
sl@0
   987
			iFlash->Write(num);
sl@0
   988
			bytesWritten++;
sl@0
   989
			}
sl@0
   990
		}		
sl@0
   991
sl@0
   992
	__KTRACE_OPT(KALWAYS, Kern::Printf("After %d attempts, we were unable to erase the flash block at [0x%X]. This could be because "
sl@0
   993
			"the driver is defective or because the flash has gone past its lifetime. Whatever it is though, "
sl@0
   994
			"we cannot continue.", KFlashEraseAttempts, aBlock.iBlockOffset));
sl@0
   995
	
sl@0
   996
	iFlash->EndTransaction();
sl@0
   997
	return KErrAbort;
sl@0
   998
	}
sl@0
   999
sl@0
  1000
/**
sl@0
  1001
 * This erases each block in the flash partition
sl@0
  1002
 * @return One of the system wide codes
sl@0
  1003
 */
sl@0
  1004
TInt SCMonitor::EraseEntireFlashPartition()
sl@0
  1005
	{
sl@0
  1006
	if(iMultiCrashInfo)
sl@0
  1007
		{
sl@0
  1008
		iMultiCrashInfo->Reset();
sl@0
  1009
		
sl@0
  1010
		SCMCrashBlockEntry* block = iMultiCrashInfo->GetNextBlock();
sl@0
  1011
		while(block)
sl@0
  1012
			{
sl@0
  1013
			TInt err = EraseFlashBlock(*block);
sl@0
  1014
			if(KErrNone != err)
sl@0
  1015
				{
sl@0
  1016
				return err;
sl@0
  1017
				}
sl@0
  1018
			
sl@0
  1019
			block = iMultiCrashInfo->GetNextBlock();
sl@0
  1020
			}
sl@0
  1021
		
sl@0
  1022
		return KErrNone;
sl@0
  1023
		}
sl@0
  1024
	
sl@0
  1025
	CLTRACE("SCMonitor::EraseEntireFlashPartition() -- No Flash MAP available, trying to use the raw driver to delete.");
sl@0
  1026
	TheSCMonitor.iFlash->EraseLogArea();
sl@0
  1027
	
sl@0
  1028
	return KErrNone;
sl@0
  1029
	}
sl@0
  1030
sl@0
  1031
//eof scmonitor.cpp
sl@0
  1032