os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/scmdatasave.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\scmdatasave.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#define __INCLUDE_REG_OFFSETS__  // for SP_R13U in nk_plat.h
sl@0
    19
sl@0
    20
#include <omap_dbg.h>
sl@0
    21
#include "arm_mem.h"
sl@0
    22
#include "nk_plat.h"
sl@0
    23
#include <omap_assp.h>
sl@0
    24
#include <scmonitor.h>
sl@0
    25
#include <scmdatasave.h> 
sl@0
    26
sl@0
    27
/**
sl@0
    28
 * @file
sl@0
    29
 * @internal technology
sl@0
    30
 */
sl@0
    31
sl@0
    32
/**
sl@0
    33
 * SCMDataSave constructor
sl@0
    34
 * @param aMonitor - the monitor which has caught the syetem crash this object is saving data for 
sl@0
    35
 * @param aFlash - the flash memory data will be written to, note the CrashFlash interface is
sl@0
    36
 * 				   rather limited and does not support partial block writes
sl@0
    37
 * @param aFlashInfo - data describing the structure of the flash data
sl@0
    38
 */
sl@0
    39
EXPORT_C SCMDataSave::SCMDataSave(Monitor* aMonitor, CrashFlash* aFlash)
sl@0
    40
	: iMonitor(aMonitor)
sl@0
    41
		,iFlash(aFlash)
sl@0
    42
		,iByteCount(0)	
sl@0
    43
#ifdef SCM_COMM_OUTPUT	
sl@0
    44
		,iWriteSelect(EWriteComm)  // write data to debug port	
sl@0
    45
#else	
sl@0
    46
		,iWriteSelect(EWriteFlash)  // write data to flash
sl@0
    47
#endif
sl@0
    48
		,iPerformChecksum(ETrue)			 // checksum data 
sl@0
    49
		,iStartingPointForCrash(0)
sl@0
    50
	{  		
sl@0
    51
	const TInt KCacheSize = 128;
sl@0
    52
	iFlashCache = HBuf8::New(KCacheSize);
sl@0
    53
	CLTRACE1("(SCMDataSave) Creating writer with cache size = %d", KCacheSize);
sl@0
    54
	iWriter = new TCachedByteStreamWriter(const_cast<TUint8*>(iFlashCache->Ptr()), KCacheSize);
sl@0
    55
	iWriter->SetWriterImpl(this);
sl@0
    56
	}
sl@0
    57
sl@0
    58
/**
sl@0
    59
 * Destructor
sl@0
    60
 */
sl@0
    61
SCMDataSave::~SCMDataSave()
sl@0
    62
	{
sl@0
    63
	delete iFlashCache;
sl@0
    64
	}
sl@0
    65
sl@0
    66
/**
sl@0
    67
 * Getter for the current byte count. This is the amount of data that has currently 
sl@0
    68
 * been written to given media for this crash log
sl@0
    69
 * @return The number of bytes written already to given media
sl@0
    70
 */
sl@0
    71
TInt SCMDataSave::GetByteCount()
sl@0
    72
	{
sl@0
    73
	return iByteCount;
sl@0
    74
	}
sl@0
    75
sl@0
    76
/**
sl@0
    77
 * Logs the user stack for a given DThread object if it is available
sl@0
    78
 * @param aThread - thread whose stack we wish to log
sl@0
    79
 * @param aSizeDumped Holds the size of the data dumped
sl@0
    80
 * @return one of the OS codes
sl@0
    81
 */
sl@0
    82
TInt SCMDataSave::LogThreadUserStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
sl@0
    83
	{
sl@0
    84
	LOG_CONTEXT
sl@0
    85
	aSizeDumped = 0;
sl@0
    86
	TUint memDumped = 0;	
sl@0
    87
	
sl@0
    88
	TUint svSp, usrSp;
sl@0
    89
	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );	
sl@0
    90
	
sl@0
    91
	//first we check for a user stack...
sl@0
    92
	if (aThread->iUserStackRunAddress && aThread->iUserStackSize)
sl@0
    93
		{		
sl@0
    94
		//Get data together
sl@0
    95
		TThreadStack usrStack;
sl@0
    96
		usrStack.iStackType = TThreadStack::EUsrStack;
sl@0
    97
		usrStack.iThreadId = (TUint64)aThread->iId;					
sl@0
    98
				
sl@0
    99
		//map in the user stack
sl@0
   100
		TUint8* usrStart = (TUint8*)iMonitor->MapAndLocateUserStack(aThread); //What about Demand paging??
sl@0
   101
		TUint8* usrEnd = (TUint8*)(usrStart + aThread->iUserStackSize);
sl@0
   102
		if(usrStart) 
sl@0
   103
			{
sl@0
   104
			TUint8* stackPointer = (TUint8*)usrSp;			
sl@0
   105
			
sl@0
   106
			//check the stack pointer is in the range of the stack...
sl@0
   107
			if (stackPointer < usrStart || stackPointer >= usrEnd)
sl@0
   108
				{
sl@0
   109
				stackPointer = usrStart;
sl@0
   110
				}
sl@0
   111
			
sl@0
   112
			//log the size of the stack we are dumping
sl@0
   113
			usrStack.iStackSize = aFullStack || (stackPointer == usrStart) ? usrEnd - usrStart : usrEnd - stackPointer;
sl@0
   114
			TUint8* dumpFrom = aFullStack ? usrStart : stackPointer;
sl@0
   115
			
sl@0
   116
			//write the stack
sl@0
   117
			aSizeDumped+= usrStack.GetSize();
sl@0
   118
			usrStack.Serialize(*iWriter);					
sl@0
   119
			
sl@0
   120
			//now we dump the actual stack
sl@0
   121
			//if there is a memErr when we read, there isnt much we can do - possibly a bit in the struct to say available/not available?
sl@0
   122
			//-1 because we dont want to write the byte at usrEnd			
sl@0
   123
			MTRAPD(memErr, LogMemory(dumpFrom, usrStack.iStackSize, aThread, memDumped));			
sl@0
   124
			if(KErrNone != memErr)
sl@0
   125
				{
sl@0
   126
				CLTRACE("Failed to log usr stack");
sl@0
   127
				}
sl@0
   128
			
sl@0
   129
			aSizeDumped+= memDumped;					
sl@0
   130
			}
sl@0
   131
		else
sl@0
   132
			{
sl@0
   133
			//write the struct
sl@0
   134
			aSizeDumped+=usrStack.GetSize();
sl@0
   135
			usrStack.Serialize(*iWriter);
sl@0
   136
			}
sl@0
   137
		}	
sl@0
   138
	return KErrNone;
sl@0
   139
	}
sl@0
   140
sl@0
   141
/**
sl@0
   142
 * Logs the supervisor stack for a given DThread object
sl@0
   143
 * @param aThread - thread whose stack we wish to log
sl@0
   144
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   145
 * @return one of the system wide codes
sl@0
   146
 */
sl@0
   147
TInt SCMDataSave::LogThreadSupervisorStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
sl@0
   148
	{	
sl@0
   149
	LOG_CONTEXT
sl@0
   150
	aSizeDumped = 0;
sl@0
   151
	TUint memDumped;	
sl@0
   152
	
sl@0
   153
	TUint svSp, usrSp;
sl@0
   154
	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
sl@0
   155
	
sl@0
   156
	//now we dump the supervisor stack
sl@0
   157
	TThreadStack svrStack;
sl@0
   158
	svrStack.iStackType = TThreadStack::ESvrStack;
sl@0
   159
	svrStack.iThreadId = (TUint64)aThread->iId;
sl@0
   160
	
sl@0
   161
	if (aThread->iSupervisorStack && aThread->iSupervisorStackSize)
sl@0
   162
		{
sl@0
   163
		TUint8* svrStart = (TUint8*)aThread->iSupervisorStack;
sl@0
   164
		TUint8* svrEnd = (TUint8*)(svrStart + aThread->iSupervisorStackSize);
sl@0
   165
		TUint8* svrStackPointer = (TUint8*)svSp;
sl@0
   166
		
sl@0
   167
		//size of stack we are to dump
sl@0
   168
		svrStack.iStackSize = aFullStack || (svrStackPointer == svrStart) ? svrEnd - svrStart  : svrEnd - svrStackPointer;					
sl@0
   169
		
sl@0
   170
		if(svrStart)
sl@0
   171
			{
sl@0
   172
			//check the stack pointer is in the range of the stack...
sl@0
   173
			if (svrStackPointer < svrStart || svrStackPointer >= svrEnd)
sl@0
   174
				{
sl@0
   175
				svrStackPointer = svrStart;
sl@0
   176
				}
sl@0
   177
sl@0
   178
			//write struct to flash
sl@0
   179
			aSizeDumped+=svrStack.GetSize();
sl@0
   180
			svrStack.Serialize(*iWriter);
sl@0
   181
			
sl@0
   182
			//now we dump the actual stack
sl@0
   183
			//if there is a memErr when we read, there isnt much we can do - possibly a bit in the struct to say available/not available?
sl@0
   184
			MTRAPD(memErr, LogMemory(svrStart, svrStack.iStackSize, aThread, memDumped));
sl@0
   185
			aSizeDumped+=memDumped;
sl@0
   186
			
sl@0
   187
			if(KErrNone != memErr)
sl@0
   188
				{
sl@0
   189
				CLTRACE("Failed to log supervisor stack");
sl@0
   190
				}						
sl@0
   191
			}
sl@0
   192
		else
sl@0
   193
			{
sl@0
   194
			//write the struct
sl@0
   195
			aSizeDumped+=svrStack.GetSize();
sl@0
   196
			svrStack.Serialize(*iWriter);
sl@0
   197
			}
sl@0
   198
		}
sl@0
   199
	
sl@0
   200
	return KErrNone;
sl@0
   201
	}
sl@0
   202
sl@0
   203
/**
sl@0
   204
 * Takes a DProcess kernel object and logs its corrosponding code segments
sl@0
   205
 * @param aProcess
sl@0
   206
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   207
 * @return one of the OS wide error codes
sl@0
   208
 */
sl@0
   209
TInt SCMDataSave::LogCodeSegments(DProcess* aProc, TUint& aSizeDumped)
sl@0
   210
	{	
sl@0
   211
	LOG_CONTEXT
sl@0
   212
	aSizeDumped = 0;	
sl@0
   213
	
sl@0
   214
	//the code segment set for this process
sl@0
   215
	TCodeSegmentSet segSet;
sl@0
   216
	segSet.iPid = (TUint64)aProc->iId;
sl@0
   217
	
sl@0
   218
	//make sure list mutex is ok
sl@0
   219
	if(Kern::CodeSegLock()->iHoldCount)
sl@0
   220
		{
sl@0
   221
		return KErrCorrupt;
sl@0
   222
		}
sl@0
   223
	
sl@0
   224
	//get code seg list
sl@0
   225
	SDblQue queue;		
sl@0
   226
	aProc->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
sl@0
   227
	
sl@0
   228
	//iterate through the list
sl@0
   229
	TInt codeSegCnt = 0;
sl@0
   230
	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
sl@0
   231
		{
sl@0
   232
		//get the code seg
sl@0
   233
		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
sl@0
   234
		
sl@0
   235
		if(codeSeg)
sl@0
   236
			{
sl@0
   237
			codeSegCnt++;
sl@0
   238
			}
sl@0
   239
		}
sl@0
   240
	
sl@0
   241
	if(codeSegCnt == 0)
sl@0
   242
		{
sl@0
   243
		return KErrNone;
sl@0
   244
		}	
sl@0
   245
	
sl@0
   246
	segSet.iNumSegs = codeSegCnt;
sl@0
   247
	segSet.Serialize(*iWriter);	
sl@0
   248
	aSizeDumped+=segSet.GetSize();
sl@0
   249
	
sl@0
   250
	TModuleMemoryInfo memoryInfo;
sl@0
   251
	
sl@0
   252
	//now we write each code segment
sl@0
   253
	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
sl@0
   254
		{
sl@0
   255
		//get the code seg
sl@0
   256
		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
sl@0
   257
		
sl@0
   258
		if(codeSeg)
sl@0
   259
			{			
sl@0
   260
			TCodeSegment seg;									
sl@0
   261
			seg.iXip = (codeSeg->iXIP) ? ETrue : EFalse;
sl@0
   262
			
sl@0
   263
			//Get the code seg type
sl@0
   264
			if(codeSeg->IsExe())
sl@0
   265
				{
sl@0
   266
				seg.iCodeSegType = EExeCodeSegType;
sl@0
   267
				}
sl@0
   268
			else if(codeSeg->IsDll())
sl@0
   269
				{
sl@0
   270
				seg.iCodeSegType = EDllCodeSegType;
sl@0
   271
				}
sl@0
   272
			
sl@0
   273
			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
sl@0
   274
			if(KErrNone == err)
sl@0
   275
				{
sl@0
   276
				seg.iCodeSegMemInfo = memoryInfo;
sl@0
   277
				}
sl@0
   278
			else
sl@0
   279
				{
sl@0
   280
				seg.iCodeSegMemInfo.iCodeSize = 0; 
sl@0
   281
sl@0
   282
				// Still need to indicate it wasnt available somehow
sl@0
   283
				}
sl@0
   284
			
sl@0
   285
			//Get filename			
sl@0
   286
			seg.iNameLength = codeSeg->iFileName->Length();
sl@0
   287
			seg.iName = *(codeSeg->iFileName);
sl@0
   288
			
sl@0
   289
			aSizeDumped+=seg.GetSize();
sl@0
   290
			seg.Serialize(*iWriter);						
sl@0
   291
			}
sl@0
   292
		}
sl@0
   293
	
sl@0
   294
	//Empty this queue and clear marks
sl@0
   295
	DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
sl@0
   296
	
sl@0
   297
	return KErrNone;
sl@0
   298
	}
sl@0
   299
sl@0
   300
/**
sl@0
   301
 * This logs the rom version and header information to the crash media
sl@0
   302
 * @param aSizeDumped amount of data occupied
sl@0
   303
 * @return one of the OS wide codes
sl@0
   304
 */
sl@0
   305
TInt SCMDataSave::LogRomInfo(TUint& aSizeDumped)	
sl@0
   306
	{
sl@0
   307
	aSizeDumped = 0;
sl@0
   308
	
sl@0
   309
	TRomHeaderData romData;
sl@0
   310
	
sl@0
   311
	TRomHeader rHdr = Epoc::RomHeader();
sl@0
   312
	
sl@0
   313
	romData.iMajorVersion = rHdr.iVersion.iMajor;
sl@0
   314
	romData.iMinorVersion = rHdr.iVersion.iMinor;
sl@0
   315
	romData.iBuildNumber = rHdr.iVersion.iBuild;
sl@0
   316
	romData.iTime = rHdr.iTime;
sl@0
   317
	
sl@0
   318
	TInt err = romData.Serialize(*iWriter);
sl@0
   319
	if(KErrNone != err)
sl@0
   320
		{
sl@0
   321
		return err;
sl@0
   322
		}
sl@0
   323
	
sl@0
   324
	aSizeDumped += romData.GetSize();
sl@0
   325
	
sl@0
   326
	return KErrNone;
sl@0
   327
	}
sl@0
   328
sl@0
   329
/**
sl@0
   330
 * Takes a DProcess kernel object and logs to flash
sl@0
   331
 * @param aProc
sl@0
   332
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   333
 * @return one of the OS wide error codes
sl@0
   334
 */
sl@0
   335
TInt SCMDataSave::LogProcessData(DProcess* aProc, TUint& aSizeDumped)
sl@0
   336
	{	
sl@0
   337
	LOG_CONTEXT
sl@0
   338
	aSizeDumped = 0;	
sl@0
   339
	
sl@0
   340
	TProcessData procData;
sl@0
   341
	DCodeSeg* codeSeg = aProc->iCodeSeg;
sl@0
   342
sl@0
   343
	procData.iPriority = aProc->iPriority;
sl@0
   344
	procData.iPid = (TUint64)aProc->iId;
sl@0
   345
	
sl@0
   346
	//the code segment is not always available
sl@0
   347
	if(codeSeg)
sl@0
   348
		{
sl@0
   349
		procData.iNamesize = codeSeg->iFileName->Length();
sl@0
   350
		procData.iName = *(codeSeg->iFileName);
sl@0
   351
		}
sl@0
   352
	
sl@0
   353
	aSizeDumped += procData.GetSize();
sl@0
   354
	procData.Serialize(*iWriter);
sl@0
   355
	
sl@0
   356
	return KErrNone;
sl@0
   357
	}
sl@0
   358
sl@0
   359
/**
sl@0
   360
 * Creates meta data about the crash such as time of crash, exit reason etc. to be logged
sl@0
   361
 * later on when we have log size.
sl@0
   362
 * @param aCategory - crash category
sl@0
   363
 * @param aReason - crash reason
sl@0
   364
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   365
 * @return one of the OS wide codes
sl@0
   366
 */
sl@0
   367
TInt SCMDataSave::LogCrashHeader(const TDesC8& aCategory, TInt aReason, TInt aCrashId, TUint& aSizeDumped)
sl@0
   368
	{
sl@0
   369
	LOG_CONTEXT
sl@0
   370
	aSizeDumped = 0;
sl@0
   371
	
sl@0
   372
	//the thread that crashed is the context in which we are running
sl@0
   373
	DThread* crashedThread = &Kern::CurrentThread();
sl@0
   374
	
sl@0
   375
	iCrashInf.iPid = crashedThread->iOwningProcess->iId; 
sl@0
   376
	iCrashInf.iTid = crashedThread->iId;
sl@0
   377
	iCrashInf.iCrashTime = CrashTime();
sl@0
   378
	iCrashInf.iExitType = 0; // Not yet done: Exception or Fault - should be in category
sl@0
   379
	iCrashInf.iExitReason = aReason;
sl@0
   380
	iCrashInf.iFlashAlign = KFlashAlignment; //record the flash alignment (word aligned for now)
sl@0
   381
	iCrashInf.iCachedWriterSize = iWriter->GetCacheSize();
sl@0
   382
	
sl@0
   383
	iCrashInf.iCategorySize = aCategory.Length();
sl@0
   384
	iCrashInf.iCategory = aCategory;	
sl@0
   385
	iCrashInf.iCrashId = aCrashId;
sl@0
   386
	
sl@0
   387
	iCrashInf.iFlashBlockSize = KCrashLogBlockSize;;
sl@0
   388
	iCrashInf.iFlashPartitionSize = KCrashLogSize;;
sl@0
   389
	
sl@0
   390
	TSuperPage& sp=Kern::SuperPage();
sl@0
   391
	iCrashInf.iExcCode = sp.iKernelExcId;
sl@0
   392
sl@0
   393
	//These will be updated with more info at end of crash
sl@0
   394
	aSizeDumped+=iCrashInf.GetSize();
sl@0
   395
	iCrashInf.Serialize(*iWriter);
sl@0
   396
	
sl@0
   397
	aSizeDumped+=iHdr.GetSize();
sl@0
   398
	iHdr.Serialize(*iWriter);		
sl@0
   399
sl@0
   400
	CLTRACE1("(SCMDataSave::LogCrashHeader) finished bytes written= %d", iWriter->GetBytesWritten());
sl@0
   401
	return KErrNone;
sl@0
   402
	}
sl@0
   403
sl@0
   404
/**
sl@0
   405
 * Logs meta data about a given DThread object
sl@0
   406
 * @param aThread Thread to dump
sl@0
   407
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   408
 * @return
sl@0
   409
 */
sl@0
   410
TInt SCMDataSave::LogThreadData(DThread* aThread, TUint& aSizeDumped)
sl@0
   411
	{
sl@0
   412
	LOG_CONTEXT
sl@0
   413
	aSizeDumped = 0;	
sl@0
   414
	
sl@0
   415
	//struct to hold data that gets written to flash
sl@0
   416
	TThreadData threadData;
sl@0
   417
	
sl@0
   418
	threadData.iTid = (TUint64)aThread->iId;
sl@0
   419
	threadData.iOwnerId = (TUint64)aThread->iOwningProcess->iId;
sl@0
   420
	threadData.iPriority = aThread->iThreadPriority;
sl@0
   421
	
sl@0
   422
	//Get the stack pointers	
sl@0
   423
	TUint svSp, usrSp;
sl@0
   424
	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
sl@0
   425
	threadData.iUsrSP = usrSp;
sl@0
   426
	threadData.iSvcSP = svSp;
sl@0
   427
		
sl@0
   428
	//supervisor and user stack details
sl@0
   429
	threadData.iSvcStack = (TInt32)aThread->iSupervisorStack;
sl@0
   430
	threadData.iSvcStacksize = aThread->iSupervisorStackSize;
sl@0
   431
	threadData.iUsrStack = aThread->iUserStackRunAddress;
sl@0
   432
	threadData.iUsrStacksize = aThread->iUserStackSize;	
sl@0
   433
	
sl@0
   434
	//currently we can only get the kernels heap
sl@0
   435
	if(aThread == &Kern::CurrentThread())
sl@0
   436
		{
sl@0
   437
		TInt32 heapLoc = 0;
sl@0
   438
		TInt32 heapSz = 0;
sl@0
   439
		TInt err = FindKernelHeap(heapLoc,heapSz);
sl@0
   440
		if(KErrNone == err)
sl@0
   441
			{
sl@0
   442
			threadData.iSvcHeap = heapLoc;
sl@0
   443
			threadData.iSvcHeapSize = heapSz;
sl@0
   444
			}
sl@0
   445
		else
sl@0
   446
			{
sl@0
   447
			CLTRACE("\tError: Unable to get kernel heap");
sl@0
   448
			}
sl@0
   449
		}	
sl@0
   450
	
sl@0
   451
	//get filename	
sl@0
   452
	TFileName filename;
sl@0
   453
	aThread->TraceAppendFullName(filename, EFalse);
sl@0
   454
	
sl@0
   455
	threadData.iName.Copy(filename);
sl@0
   456
	threadData.iNamesize = threadData.iName.Length();
sl@0
   457
	
sl@0
   458
		
sl@0
   459
#ifdef __INCLUDE_NTHREADBASE_DEFINES__
sl@0
   460
	threadData.iLastCpu = aThread->iNThread.iLastCpu;
sl@0
   461
#else	
sl@0
   462
	threadData.iLastCpu = aThread->iNThread.iSpare3;	
sl@0
   463
#endif	
sl@0
   464
	
sl@0
   465
	threadData.Serialize(*iWriter);
sl@0
   466
	aSizeDumped+=threadData.GetSize();
sl@0
   467
	
sl@0
   468
	return KErrNone;
sl@0
   469
	}
sl@0
   470
sl@0
   471
/**
sl@0
   472
 * Logs the arm exception stacks 
sl@0
   473
 * @param aSizeDumped Holds the size of the data dumped 
sl@0
   474
 * @return one of the OS wide codes
sl@0
   475
 */
sl@0
   476
TInt SCMDataSave::LogExceptionStacks(TUint& aSizeDumped)
sl@0
   477
	{
sl@0
   478
	LOG_CONTEXT
sl@0
   479
	aSizeDumped = 0;
sl@0
   480
	TUint memDumped = 0;
sl@0
   481
	
sl@0
   482
	#if defined(__EPOC32__) && !defined(__CPU_X86)
sl@0
   483
sl@0
   484
	TStackInfo& stackInfo = Kern::SuperPage().iStackInfo;
sl@0
   485
sl@0
   486
	TThreadStack irqStack;
sl@0
   487
	irqStack.iStackType = TThreadStack::EIRQStack;
sl@0
   488
	irqStack.iStackSize = stackInfo.iIrqStackSize;
sl@0
   489
	
sl@0
   490
	aSizeDumped+=irqStack.GetSize();
sl@0
   491
	irqStack.Serialize(*iWriter);
sl@0
   492
	
sl@0
   493
	//now dump the IRQ memory - not much we can do in the event of an error
sl@0
   494
	MTRAPD(irqErr, LogMemory((TUint8*)stackInfo.iIrqStackBase, stackInfo.iIrqStackSize, &Kern::CurrentThread(), memDumped));	
sl@0
   495
	
sl@0
   496
	if(KErrNone != irqErr)
sl@0
   497
		{
sl@0
   498
		CLTRACE("*****Failed to log IRQ stack");
sl@0
   499
		}
sl@0
   500
	aSizeDumped+=memDumped;
sl@0
   501
	
sl@0
   502
	//Next, we do the FIQ stack
sl@0
   503
	TThreadStack fiqStack;
sl@0
   504
	fiqStack.iStackType = TThreadStack::EFIQStack;
sl@0
   505
	fiqStack.iStackSize = stackInfo.iFiqStackSize;
sl@0
   506
	
sl@0
   507
	aSizeDumped+=fiqStack.GetSize();
sl@0
   508
	fiqStack.Serialize(*iWriter);
sl@0
   509
	
sl@0
   510
	//Now dump the stack itself
sl@0
   511
	MTRAPD(fiqErr, LogMemory((TUint8*)stackInfo.iFiqStackBase, stackInfo.iFiqStackSize, &Kern::CurrentThread(), memDumped));
sl@0
   512
	
sl@0
   513
	if(KErrNone != fiqErr )
sl@0
   514
		{
sl@0
   515
		CLTRACE("*****Failed to log FIQ stack");
sl@0
   516
		}
sl@0
   517
	aSizeDumped+=memDumped;
sl@0
   518
sl@0
   519
	#endif
sl@0
   520
	
sl@0
   521
	return KErrNone;
sl@0
   522
	}
sl@0
   523
sl@0
   524
/**
sl@0
   525
 * Logs the CPU Registers at the time of crash
sl@0
   526
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   527
 * @return system wide OS code
sl@0
   528
 */
sl@0
   529
TInt SCMDataSave::LogCPURegisters(TUint& aSizeDumped)
sl@0
   530
	{
sl@0
   531
	LOG_CONTEXT
sl@0
   532
	aSizeDumped = 0;
sl@0
   533
	
sl@0
   534
	TInt32 fullSet = 37;
sl@0
   535
	
sl@0
   536
	//meta data about the thread set
sl@0
   537
	TRegisterSet threadSet;
sl@0
   538
	threadSet.iNumRegisters = fullSet;
sl@0
   539
	
sl@0
   540
	aSizeDumped+=threadSet.GetSize();
sl@0
   541
	threadSet.Serialize(*iWriter);
sl@0
   542
		
sl@0
   543
	SFullArmRegSet regSet;
sl@0
   544
	ReadCPURegisters(regSet);
sl@0
   545
	TArmReg* regs = (TArmReg*)&regSet;
sl@0
   546
		
sl@0
   547
	TInt32 cnt = 0;
sl@0
   548
	for(cnt = 0; cnt < fullSet; cnt++)
sl@0
   549
		{			
sl@0
   550
		//this is the struct to store the register value in
sl@0
   551
		TRegisterValue regVal;
sl@0
   552
		regVal.iType = cnt * 0x100;
sl@0
   553
		regVal.iValue32 = regs[cnt];
sl@0
   554
		regVal.iOwnId = Kern::CurrentThread().iId;
sl@0
   555
		
sl@0
   556
		aSizeDumped+=regVal.GetSize();
sl@0
   557
		regVal.Serialize(*iWriter);
sl@0
   558
		}
sl@0
   559
sl@0
   560
	return KErrNone;	
sl@0
   561
	}
sl@0
   562
sl@0
   563
/**
sl@0
   564
 * This logs the registers for a given thread to the flash memory
sl@0
   565
 * @param aThread - thread whose registers we want
sl@0
   566
 * @param aRegType - type of register set required such as user, supervisor etc
sl@0
   567
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   568
 * @return one of the OS return codes
sl@0
   569
 */
sl@0
   570
TInt SCMDataSave::LogRegisters(DThread* aThread, const TRegisterSetType& aRegType, TUint& aSizeDumped)
sl@0
   571
	{
sl@0
   572
	LOG_CONTEXT
sl@0
   573
	aSizeDumped = 0;
sl@0
   574
	
sl@0
   575
	TArmRegSet regs;
sl@0
   576
	TUint32 availableRegs;
sl@0
   577
	TInt err;
sl@0
   578
	
sl@0
   579
	//for the current thread we do things differently
sl@0
   580
	if(aThread == &Kern::CurrentThread() && aRegType == EFullCPURegisters)
sl@0
   581
		{
sl@0
   582
		err = LogCPURegisters(aSizeDumped);
sl@0
   583
		return err;
sl@0
   584
		} 
sl@0
   585
	else if(aThread == &Kern::CurrentThread())
sl@0
   586
		{
sl@0
   587
		//only do full cpu reg for the current thread
sl@0
   588
		return KErrNotSupported;
sl@0
   589
		}
sl@0
   590
	
sl@0
   591
	//Read the appropriate registers
sl@0
   592
	switch(aRegType)
sl@0
   593
		{
sl@0
   594
		case EUserRegisters :
sl@0
   595
			{
sl@0
   596
			err = ReadUserRegisters(aThread, regs, availableRegs);
sl@0
   597
			break;
sl@0
   598
			}
sl@0
   599
		case ESupervisorRegisters :
sl@0
   600
			{
sl@0
   601
			err = ReadSystemRegisters(aThread, regs, availableRegs);
sl@0
   602
			break;			
sl@0
   603
			}
sl@0
   604
		default : return KErrNotSupported;
sl@0
   605
		}
sl@0
   606
	
sl@0
   607
	if(err != KErrNone)
sl@0
   608
		{
sl@0
   609
		return err;
sl@0
   610
		}	
sl@0
   611
		
sl@0
   612
	//meta data about the thread set
sl@0
   613
	TRegisterSet threadSet;
sl@0
   614
	
sl@0
   615
	//to get the number of registers in advance, we need to count the number of times 1 is set in the bit field of availableRegs
sl@0
   616
	TUint numR = 0;
sl@0
   617
	for(TInt cnt =0; cnt< 8*sizeof(availableRegs); cnt++) //cycle through 1 bit at a time
sl@0
   618
		{
sl@0
   619
		if(0x1 & (availableRegs>>cnt))
sl@0
   620
			numR++;
sl@0
   621
		}
sl@0
   622
	
sl@0
   623
	threadSet.iNumRegisters = numR;
sl@0
   624
	
sl@0
   625
	if(numR == 0)
sl@0
   626
		return KErrNone;
sl@0
   627
	
sl@0
   628
	threadSet.Serialize(*iWriter);
sl@0
   629
	aSizeDumped += threadSet.GetSize();
sl@0
   630
	
sl@0
   631
	TInt32 currentRegister = 1;
sl@0
   632
	TArmReg* reg = (TArmReg*)(&regs);	
sl@0
   633
	
sl@0
   634
	for(TInt32 cnt = 0; cnt < KArmRegisterCount; cnt++)
sl@0
   635
		{		
sl@0
   636
		//look at the unavailable bitmask to see current register is available
sl@0
   637
		//only write the registers we have values for
sl@0
   638
		if(currentRegister & availableRegs)
sl@0
   639
			{
sl@0
   640
			//this is the struct to store the register value in
sl@0
   641
			TRegisterValue regVal;
sl@0
   642
						
sl@0
   643
			//get register type as per symbian elf docs
sl@0
   644
			TUint32 registerType;
sl@0
   645
			err = GetRegisterType(aRegType, cnt, registerType);
sl@0
   646
			if(err != KErrNone)
sl@0
   647
				{
sl@0
   648
				continue;
sl@0
   649
				}
sl@0
   650
			regVal.iType = registerType;
sl@0
   651
			regVal.iOwnId = aThread->iId;
sl@0
   652
			
sl@0
   653
			//set value
sl@0
   654
			regVal.iValue32 = reg[cnt];
sl@0
   655
			
sl@0
   656
			aSizeDumped+=regVal.GetSize();
sl@0
   657
			regVal.Serialize(*iWriter);
sl@0
   658
			}
sl@0
   659
		
sl@0
   660
		currentRegister<<=1; 
sl@0
   661
		}
sl@0
   662
	
sl@0
   663
	return KErrNone;
sl@0
   664
	}
sl@0
   665
sl@0
   666
/**
sl@0
   667
 * This logs memory in the specified area
sl@0
   668
 * @param aStartAddress - address to start from
sl@0
   669
 * @param aEndAddress - address to finish
sl@0
   670
 * @param aThread - process whose memory this is in
sl@0
   671
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   672
 * @return one of the system wide codes
sl@0
   673
 */
sl@0
   674
TInt SCMDataSave::LogMemory(const TUint8* aStartAddress, TInt aLength, const DThread* aThread, TUint& aSizeDumped)
sl@0
   675
	{
sl@0
   676
	LOG_CONTEXT
sl@0
   677
	aSizeDumped = 0;	
sl@0
   678
	
sl@0
   679
	if(aThread->iOwningProcess != &Kern::CurrentProcess())
sl@0
   680
		{
sl@0
   681
		TInt err = iMonitor->SwitchAddressSpace(aThread->iOwningProcess, ETrue);
sl@0
   682
		if(KErrNone != err)
sl@0
   683
			{
sl@0
   684
			return err;
sl@0
   685
			}
sl@0
   686
		}
sl@0
   687
	
sl@0
   688
	TMemoryDump memDump;
sl@0
   689
	memDump.iStartAddress = (TUint32)aStartAddress;
sl@0
   690
	memDump.iLength = aLength;
sl@0
   691
	memDump.iPid = aThread->iOwningProcess->iId;
sl@0
   692
	
sl@0
   693
	aSizeDumped+=memDump.GetSize();
sl@0
   694
	memDump.Serialize(*iWriter);	
sl@0
   695
	
sl@0
   696
	if(!aStartAddress)
sl@0
   697
		{
sl@0
   698
		return KErrArgument;
sl@0
   699
		}
sl@0
   700
	
sl@0
   701
	TRawData theMemory;
sl@0
   702
	theMemory.iData.Set(const_cast<TUint8*>(aStartAddress), aLength, aLength);
sl@0
   703
	
sl@0
   704
	theMemory.Serialize(*iWriter);
sl@0
   705
	aSizeDumped+=theMemory.GetSize();
sl@0
   706
	
sl@0
   707
	return KErrNone;	
sl@0
   708
	}
sl@0
   709
sl@0
   710
/**
sl@0
   711
 * This logs the locks held by system at time of crash
sl@0
   712
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   713
 * @return one of the system wide codes
sl@0
   714
 */
sl@0
   715
TInt SCMDataSave::LogLocks(TUint& aSizeDumped)
sl@0
   716
	{
sl@0
   717
	LOG_CONTEXT
sl@0
   718
	aSizeDumped = 0;
sl@0
   719
	
sl@0
   720
	// get the mutex logs & waits & log via a TLockData object		
sl@0
   721
	TSCMLockData lockData;
sl@0
   722
sl@0
   723
	const TInt KMaxLockCheck = 20; // so no possibility of infinite loop
sl@0
   724
		
sl@0
   725
	TInt lockCount = 0;
sl@0
   726
	// check for kernel locks - 	
sl@0
   727
	for(TInt i=0;i<KMaxLockCheck;i++)
sl@0
   728
		{		
sl@0
   729
		TBool locked = NKern::KernelLocked(i);	
sl@0
   730
		if(!locked)
sl@0
   731
			{
sl@0
   732
			lockData.SetLockCount(lockCount);
sl@0
   733
			break;		
sl@0
   734
			}
sl@0
   735
		// found a valid lock for value i increment the clock counter
sl@0
   736
		lockCount++;
sl@0
   737
		}
sl@0
   738
	
sl@0
   739
	// now mutexes
sl@0
   740
	DMutex* mutex = Kern::CodeSegLock();
sl@0
   741
	if(mutex)
sl@0
   742
		{
sl@0
   743
		lockData.SetMutexHoldCount(mutex->iHoldCount);
sl@0
   744
		lockData.SetMutexThreadWaitCount(mutex->iWaitCount);
sl@0
   745
		}
sl@0
   746
	else
sl@0
   747
		{
sl@0
   748
		// no mutex held set to -1
sl@0
   749
		lockData.SetMutexHoldCount(0);
sl@0
   750
		lockData.SetMutexThreadWaitCount(0);		
sl@0
   751
		}
sl@0
   752
sl@0
   753
	aSizeDumped+=lockData.GetSize();
sl@0
   754
	TInt err = lockData.Serialize(*iWriter);
sl@0
   755
	
sl@0
   756
	return err;
sl@0
   757
	}
sl@0
   758
sl@0
   759
/**
sl@0
   760
 * Writes the SCM Configuration to the start of the media
sl@0
   761
 * @param aScmConfig Configuration to write
sl@0
   762
 * @return one of the system wide codes
sl@0
   763
 */
sl@0
   764
TInt SCMDataSave::LogConfig(SCMConfiguration& aScmConfig)
sl@0
   765
	{
sl@0
   766
	iWriter->SetPosition(0);
sl@0
   767
	
sl@0
   768
	TInt err = aScmConfig.Serialize(*iWriter);
sl@0
   769
	
sl@0
   770
	if( err != KErrNone)
sl@0
   771
		{
sl@0
   772
		CLTRACE1("SCMDataSave::LogConfig failed err = %d", err);
sl@0
   773
		}
sl@0
   774
sl@0
   775
	return err;
sl@0
   776
	}
sl@0
   777
sl@0
   778
/**
sl@0
   779
 * Reads the SCM Configuration from the media
sl@0
   780
 * @param aScmConfig
sl@0
   781
 * @return one of the system wide codes
sl@0
   782
 */
sl@0
   783
TInt SCMDataSave::ReadConfig(SCMConfiguration& aScmConfig)
sl@0
   784
	{		
sl@0
   785
	const TInt KBufSize = 135; //Not yet done: Put in header, beside config defn
sl@0
   786
sl@0
   787
	if( KBufSize < aScmConfig.GetSize())
sl@0
   788
		{
sl@0
   789
		CLTRACE2("(SCMDataSave::ReadConfig) ** ERROR Inadequate buffer actual = %d req = %d"
sl@0
   790
				, KBufSize,  aScmConfig.GetSize());	
sl@0
   791
		}
sl@0
   792
	
sl@0
   793
	// try and read the configuration
sl@0
   794
	TBuf8<KBufSize> buf;
sl@0
   795
	buf.SetLength(KBufSize);
sl@0
   796
		
sl@0
   797
	iFlash->SetReadPos(0); // config always at 0
sl@0
   798
	iFlash->Read(buf);
sl@0
   799
	 
sl@0
   800
	TByteStreamReader reader(const_cast<TUint8*>(buf.Ptr()));		
sl@0
   801
	TInt err = aScmConfig.Deserialize(reader);	
sl@0
   802
	if(err == KErrNotReady)
sl@0
   803
		{
sl@0
   804
		CLTRACE("(SCMDataSave::ReadConfig) no config saved - use default");
sl@0
   805
		}	
sl@0
   806
	else if(err == KErrNone)	
sl@0
   807
		{
sl@0
   808
		CLTRACE("(SCMDataSave::ReadConfig) Config read ok"); 		
sl@0
   809
		}
sl@0
   810
	else
sl@0
   811
		{
sl@0
   812
		CLTRACE1("(SCMDataSave::ReadConfig) error reading config err = %d", err); 
sl@0
   813
		}
sl@0
   814
	
sl@0
   815
	return err;
sl@0
   816
	}
sl@0
   817
sl@0
   818
/**
sl@0
   819
 * This is a look up table to map the register type and number to the symbian elf definition 
sl@0
   820
 * of register type
sl@0
   821
 * @param aSetType this is the register set type - user, supervisor etc
sl@0
   822
 * @param aRegNumber this is the number of the register as per TArmRegisters in arm_types.h
sl@0
   823
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   824
 * @return One of the OS wide codes
sl@0
   825
 */
sl@0
   826
TInt SCMDataSave::GetRegisterType(const TRegisterSetType& aSetType, TInt32& aRegNumber, TUint32& aRegisterType)
sl@0
   827
	{	
sl@0
   828
	//validate arguments
sl@0
   829
	if(aRegNumber < EArmR0 || aRegNumber > EArmFlags)
sl@0
   830
		{
sl@0
   831
		return KErrArgument;
sl@0
   832
		}
sl@0
   833
	
sl@0
   834
	//look at what type we are using
sl@0
   835
	switch(aSetType)
sl@0
   836
		{
sl@0
   837
		case EUserRegisters :
sl@0
   838
			{
sl@0
   839
			aRegisterType = aRegNumber * 0x100; //for R0 to R16 (CPSR) it just increments in 0x100 from 0x0 to 0x1000
sl@0
   840
			break;
sl@0
   841
			}
sl@0
   842
		case ESupervisorRegisters :
sl@0
   843
			{
sl@0
   844
			//same as EUserRegisters except R13 and R14 are different
sl@0
   845
			if(aRegNumber == EArmSp)
sl@0
   846
				{
sl@0
   847
				aRegisterType = 0x1100;
sl@0
   848
				break;
sl@0
   849
				}
sl@0
   850
			else if(aRegNumber == EArmLr)
sl@0
   851
				{
sl@0
   852
				aRegisterType = 0x1200;
sl@0
   853
				break;
sl@0
   854
				}
sl@0
   855
			else
sl@0
   856
				{
sl@0
   857
				aRegisterType = aRegNumber * 0x100;
sl@0
   858
				break;
sl@0
   859
				}		
sl@0
   860
			}
sl@0
   861
		default : return KErrNotSupported;
sl@0
   862
		}
sl@0
   863
	
sl@0
   864
	return KErrNone;
sl@0
   865
	}
sl@0
   866
sl@0
   867
/**
sl@0
   868
 * Writes the trace buffer to the crash log. 
sl@0
   869
 * @param aSizeToDump Number of bytes to dump. If this is zero we attempt to write the entire buffer
sl@0
   870
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   871
 * @return One of the OS wide codes
sl@0
   872
 */
sl@0
   873
TInt SCMDataSave::LogTraceBuffer(TInt aSizeToDump, TUint& aSizeDumped)
sl@0
   874
	{
sl@0
   875
	LOG_CONTEXT
sl@0
   876
	aSizeDumped = 0;
sl@0
   877
	TUint memDumped = 0;
sl@0
   878
	
sl@0
   879
	TBool dumpAll = (aSizeToDump == 0) ? ETrue : EFalse;
sl@0
   880
	
sl@0
   881
	//Because the btrace buffer is a circular one, we need to save it in two parts
sl@0
   882
	//this corrosponds to how we read it	
sl@0
   883
	TUint8* data;
sl@0
   884
	TUint sizeOfPartRead;
sl@0
   885
	TInt spaceRemaining = aSizeToDump;
sl@0
   886
	
sl@0
   887
	//This structure will be filled after the first pass and cached so by the time we ARE writing it will
sl@0
   888
	//contain the data we want 
sl@0
   889
	aSizeDumped+=iTrace.GetSize();
sl@0
   890
	iTrace.Serialize(*iWriter);
sl@0
   891
	
sl@0
   892
	//read first part
sl@0
   893
	TInt err = BTrace::Control(BTrace::ECtrlCrashReadFirst,&data,&sizeOfPartRead);
sl@0
   894
	
sl@0
   895
	while(KErrNone == err && sizeOfPartRead > 0)
sl@0
   896
		{
sl@0
   897
		TUint rawSize = 0; //how much of this read data want we to dump
sl@0
   898
		
sl@0
   899
		if(dumpAll)
sl@0
   900
			{
sl@0
   901
			rawSize = sizeOfPartRead;
sl@0
   902
			}
sl@0
   903
		else	//Otherwise see what room is left for dumpage
sl@0
   904
			{
sl@0
   905
			rawSize  = ((sizeOfPartRead + iTrace.iSizeOfMemory) > aSizeToDump) ? spaceRemaining : sizeOfPartRead;
sl@0
   906
			}		
sl@0
   907
		
sl@0
   908
		//Only relevant if restricting the dump
sl@0
   909
		if(spaceRemaining <= 0 && !dumpAll)
sl@0
   910
			break;
sl@0
   911
		
sl@0
   912
		TPtrC8 ptr(data, rawSize);
sl@0
   913
		err = LogRawData(ptr, memDumped);
sl@0
   914
		if(KErrNone != err)
sl@0
   915
			{
sl@0
   916
			CLTRACE1("Logging Raw data failed - [%d]", err);
sl@0
   917
			err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
sl@0
   918
			continue;
sl@0
   919
			}
sl@0
   920
		
sl@0
   921
		aSizeDumped+=memDumped;
sl@0
   922
		
sl@0
   923
		iTrace.iSizeOfMemory += rawSize;
sl@0
   924
		iTrace.iNumberOfParts++;
sl@0
   925
		spaceRemaining -= rawSize;		
sl@0
   926
		
sl@0
   927
		err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
sl@0
   928
		}
sl@0
   929
	
sl@0
   930
	return KErrNone;
sl@0
   931
	}
sl@0
   932
sl@0
   933
/**
sl@0
   934
 * Logs the data in a TRawData struct
sl@0
   935
 * @param aData 
sl@0
   936
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   937
 * @return One of the OS wide codes
sl@0
   938
 */
sl@0
   939
TInt SCMDataSave::LogRawData(const TDesC8& aData, TUint& aSizeDumped)
sl@0
   940
	{
sl@0
   941
	TRawData theData;
sl@0
   942
	theData.iLength = aData.Length();
sl@0
   943
	theData.iData.Set(const_cast<TUint8*>(aData.Ptr()), aData.Length(), aData.Length());
sl@0
   944
	
sl@0
   945
	aSizeDumped+=theData.GetSize();
sl@0
   946
	return theData.Serialize(*iWriter);	
sl@0
   947
	}
sl@0
   948
sl@0
   949
sl@0
   950
/**
sl@0
   951
 * Logs the kernels heap and returns the size dumped via aSizeDumped
sl@0
   952
 * @param aSizeDumped Holds the size of the data dumped
sl@0
   953
 * @return
sl@0
   954
 */
sl@0
   955
TInt SCMDataSave::LogKernelHeap(TUint& aSizeDumped)
sl@0
   956
	{
sl@0
   957
	LOG_CONTEXT
sl@0
   958
	
sl@0
   959
	TInt32 heapLoc = 0;
sl@0
   960
	TInt32 heapSize = 0;
sl@0
   961
	TInt32 err = FindKernelHeap(heapLoc, heapSize);
sl@0
   962
	if(KErrNone == err)
sl@0
   963
		{
sl@0
   964
		return LogMemory((TUint8*)heapLoc, heapSize, &Kern::CurrentThread(), aSizeDumped);
sl@0
   965
		}
sl@0
   966
	
sl@0
   967
	CLTRACE1("\tCouldnt find the kernel heap: [%d]", err);
sl@0
   968
	return err;
sl@0
   969
	}
sl@0
   970
sl@0
   971
/**
sl@0
   972
 * Iterates the object containers and finds the kernel heap
sl@0
   973
 * @param aHeapLocation Contains the memory location of the kernel heap
sl@0
   974
 * @param aHeapSize Contains the size of the Heap
sl@0
   975
 * @return One of the OS wide codes
sl@0
   976
 */
sl@0
   977
TInt SCMDataSave::FindKernelHeap(TInt32& aHeapLocation, TInt32& aHeapSize)
sl@0
   978
	{
sl@0
   979
	LOG_CONTEXT
sl@0
   980
	
sl@0
   981
	//Get Chunk object container
sl@0
   982
	DObjectCon* objectContainer = Kern::Containers()[EChunk];
sl@0
   983
	if(objectContainer == NULL)
sl@0
   984
		{		
sl@0
   985
		CLTRACE("\tFailed to get object container for the chunks");
sl@0
   986
		return KErrNotFound;
sl@0
   987
		}
sl@0
   988
	
sl@0
   989
	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
sl@0
   990
	if(objectContainer->Lock()->iHoldCount)
sl@0
   991
		{
sl@0
   992
		CLTRACE("\tChunk Container is in an inconsistant state");
sl@0
   993
		return KErrCorrupt;
sl@0
   994
		}
sl@0
   995
	
sl@0
   996
	TInt numObjects = objectContainer->Count();	
sl@0
   997
	
sl@0
   998
	for(TInt cnt = 0; cnt< numObjects; cnt ++)
sl@0
   999
		{		
sl@0
  1000
		DChunk* candidateHeapChunk = (DChunk*)(*objectContainer)[cnt];
sl@0
  1001
		
sl@0
  1002
		//Get the objects name
sl@0
  1003
		TBuf8<KMaxKernelName> name;
sl@0
  1004
		candidateHeapChunk->TraceAppendFullName(name,EFalse);
sl@0
  1005
		
sl@0
  1006
		if(name == KKernelHeapChunkName)
sl@0
  1007
			{
sl@0
  1008
			#ifndef __MEMMODEL_FLEXIBLE__
sl@0
  1009
				aHeapLocation = (TInt32)candidateHeapChunk->iBase;
sl@0
  1010
			#else
sl@0
  1011
				aHeapLocation = (TInt32)candidateHeapChunk->iFixedBase;
sl@0
  1012
			#endif
sl@0
  1013
				
sl@0
  1014
				aHeapSize = candidateHeapChunk->iSize;
sl@0
  1015
				
sl@0
  1016
			return KErrNone;
sl@0
  1017
			}
sl@0
  1018
		}
sl@0
  1019
	
sl@0
  1020
	return KErrNotFound;
sl@0
  1021
	}
sl@0
  1022
sl@0
  1023
/**
sl@0
  1024
 * This logs the variant specific descriptor data to the crash log
sl@0
  1025
 * @param aSizeDumped records how much was dumped by this function
sl@0
  1026
 * @return one of the OS wide codes
sl@0
  1027
 */
sl@0
  1028
TInt SCMDataSave::LogVariantSpecificData(TUint& aSizeDumped)
sl@0
  1029
	{
sl@0
  1030
	LOG_CONTEXT
sl@0
  1031
	
sl@0
  1032
	aSizeDumped = 0;
sl@0
  1033
	
sl@0
  1034
	//Change this descriptor as required for your needs
sl@0
  1035
	_LIT(KVariantSpecificData, "This is the variant specific data. Put your own here");
sl@0
  1036
	
sl@0
  1037
	TVariantSpecificData varData;
sl@0
  1038
	varData.iSize = KVariantSpecificData().Size(); 
sl@0
  1039
	
sl@0
  1040
	TInt err = varData.Serialize(*iWriter);
sl@0
  1041
	if(KErrNone != err)
sl@0
  1042
		{
sl@0
  1043
		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
sl@0
  1044
		return err;
sl@0
  1045
		}
sl@0
  1046
	aSizeDumped+=varData.GetSize();
sl@0
  1047
	
sl@0
  1048
	TUint rawDataSize = 0;
sl@0
  1049
	err = LogRawData(KVariantSpecificData(), rawDataSize);
sl@0
  1050
	if(KErrNone != err)
sl@0
  1051
		{
sl@0
  1052
		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
sl@0
  1053
		return err;
sl@0
  1054
		}
sl@0
  1055
	
sl@0
  1056
	aSizeDumped+=rawDataSize;
sl@0
  1057
	
sl@0
  1058
	return KErrNone;
sl@0
  1059
	}
sl@0
  1060
sl@0
  1061
sl@0
  1062
/**
sl@0
  1063
 * This method is the callback used by MPhysicalWriterImpl interface
sl@0
  1064
 * if the TCachedByteStreamWriter is configured to use this interface
sl@0
  1065
 * the callback avoids the need for temp buffers & can interface directly with the
sl@0
  1066
 * flash writer methods
sl@0
  1067
 * @param aData - data to write
sl@0
  1068
 * @param aLen	- length of data to write
sl@0
  1069
 * @param aPos  - writers internal position   
sl@0
  1070
 */
sl@0
  1071
void SCMDataSave::DoPhysicalWrite(TAny* aData, TInt aPos, TInt aLen)
sl@0
  1072
	{	
sl@0
  1073
	if(iPerformChecksum)
sl@0
  1074
		{
sl@0
  1075
		iChecksum.ChecksumBlock((TUint8*)aData, aLen);
sl@0
  1076
		}
sl@0
  1077
	
sl@0
  1078
	if( this->iWriteSelect == EWriteComm)
sl@0
  1079
		{	
sl@0
  1080
		WriteUart((TUint8*)aData, aLen);		
sl@0
  1081
		}
sl@0
  1082
	else  // EWriteFlash
sl@0
  1083
		{			
sl@0
  1084
		Write(aData, aLen);
sl@0
  1085
		}
sl@0
  1086
	}
sl@0
  1087
sl@0
  1088
/**
sl@0
  1089
 * Writes data to Flash
sl@0
  1090
 * @param aSomething Pointer to the data
sl@0
  1091
 * @param aSize Size of the data
sl@0
  1092
 */
sl@0
  1093
void SCMDataSave::Write(const TAny* aSomething, TInt aSize)
sl@0
  1094
	{		
sl@0
  1095
	TPtrC8 data((const TUint8 *)aSomething, aSize);
sl@0
  1096
	
sl@0
  1097
	TInt written = 0;
sl@0
  1098
	
sl@0
  1099
	WriteCrashFlash(iByteCount, written, data);
sl@0
  1100
	iByteCount+= written;	
sl@0
  1101
	}
sl@0
  1102
sl@0
  1103
/**
sl@0
  1104
 * Writes a descriptor to the crash flash
sl@0
  1105
 * @param aPos Position in flash to write
sl@0
  1106
 * @param aSize Holds the size of the data written after the call
sl@0
  1107
 * @param aBuffer Descriptor to write
sl@0
  1108
 */
sl@0
  1109
void SCMDataSave::WriteCrashFlash(TInt aPos, TInt& aSize, const TDesC8& aBuffer)
sl@0
  1110
	{	
sl@0
  1111
	//Set write position in the flash
sl@0
  1112
	iFlash->SetWritePos(aPos);	
sl@0
  1113
	iFlash->Write(aBuffer);
sl@0
  1114
	
sl@0
  1115
	//get bytes written
sl@0
  1116
	aSize += iFlash->BytesWritten();
sl@0
  1117
	
sl@0
  1118
	if(aSize != aBuffer.Length())
sl@0
  1119
		{
sl@0
  1120
		CLTRACE2("(SCMDataSave::WriteCrashFlash) Over the limit aSize = %d aBuffer.Length() = %d",
sl@0
  1121
				aSize,  aBuffer.Length());
sl@0
  1122
		}
sl@0
  1123
	}
sl@0
  1124
	
sl@0
  1125
/**
sl@0
  1126
 * Writes a descriptor via serial
sl@0
  1127
 * @param aDes Descriptor to write
sl@0
  1128
 */
sl@0
  1129
void SCMDataSave::WriteUart(const TDesC8& aDes)
sl@0
  1130
	{
sl@0
  1131
	WriteUart(aDes.Ptr(), aDes.Length());	
sl@0
  1132
	}
sl@0
  1133
sl@0
  1134
/**
sl@0
  1135
 * Writes data via serial
sl@0
  1136
 * @param aData Data to write
sl@0
  1137
 * @param aSize Size of data to write
sl@0
  1138
 */
sl@0
  1139
void SCMDataSave::WriteUart(const TUint8* aData, TInt aSize)
sl@0
  1140
	{
sl@0
  1141
	OMAP* assp = ((OMAP*)Arch::TheAsic());
sl@0
  1142
	TOmapDbgPrt* dbg = assp->DebugPort();
sl@0
  1143
		
sl@0
  1144
	if (dbg)
sl@0
  1145
		{
sl@0
  1146
		for(TInt i=0;i<aSize;i++)
sl@0
  1147
			{
sl@0
  1148
			dbg->DebugOutput(*(aData+i));			
sl@0
  1149
			}
sl@0
  1150
		}
sl@0
  1151
	else
sl@0
  1152
		{
sl@0
  1153
		CLTRACE("SCMDataSave::WriteUart ERROR - dbg was null");		
sl@0
  1154
		}
sl@0
  1155
	}
sl@0
  1156
sl@0
  1157
/**
sl@0
  1158
 * Setter for the current number of bytes written for this crash log
sl@0
  1159
 * If aByte is not word aligned, it will be rounded up to be so
sl@0
  1160
 * @param aByte Current bytes written
sl@0
  1161
 */
sl@0
  1162
void SCMDataSave::SetByteCount(TInt aByte)
sl@0
  1163
	{
sl@0
  1164
	//ensure aligned
sl@0
  1165
	if(aByte % iWriter->GetCacheSize() == 0)
sl@0
  1166
		{
sl@0
  1167
		iByteCount = aByte;
sl@0
  1168
		}
sl@0
  1169
	else
sl@0
  1170
		{
sl@0
  1171
		iByteCount = aByte + (iWriter->GetCacheSize() - (aByte % iWriter->GetCacheSize()));
sl@0
  1172
		}		
sl@0
  1173
	}
sl@0
  1174
sl@0
  1175
/**
sl@0
  1176
 * Gets the output target selection
sl@0
  1177
 * @return TScmWriteSelect output target selection
sl@0
  1178
 * @param void
sl@0
  1179
 */	
sl@0
  1180
SCMDataSave::TWriteSelect SCMDataSave::GetWriteSelect()
sl@0
  1181
	{
sl@0
  1182
	return iWriteSelect;
sl@0
  1183
	}
sl@0
  1184
sl@0
  1185
/**
sl@0
  1186
 * Sets the output target selection
sl@0
  1187
 * @return void
sl@0
  1188
 * @param TScmWriteSelect aWriteSelect output target selection
sl@0
  1189
 */
sl@0
  1190
void SCMDataSave::SetWriteSelect(SCMDataSave::TWriteSelect aWriteSelect)
sl@0
  1191
	{
sl@0
  1192
	iWriteSelect = aWriteSelect;
sl@0
  1193
	}
sl@0
  1194
sl@0
  1195
/**
sl@0
  1196
 * Gets the amount of space remaining for the media of choice
sl@0
  1197
 * @return
sl@0
  1198
 */
sl@0
  1199
TUint SCMDataSave::SpaceRemaining()
sl@0
  1200
	{
sl@0
  1201
	TInt currentPosition = iWriter->GetBytesWritten() + iStartingPointForCrash;
sl@0
  1202
	
sl@0
  1203
	return MaxLogSize() - currentPosition; 
sl@0
  1204
	}
sl@0
  1205
sl@0
  1206
/**
sl@0
  1207
 * To find the max size of a log for a given media
sl@0
  1208
 * @return the max size of a log for a given media
sl@0
  1209
 */
sl@0
  1210
TUint SCMDataSave::MaxLogSize()
sl@0
  1211
	{
sl@0
  1212
	//see what write media is being used
sl@0
  1213
	switch(GetWriteSelect())
sl@0
  1214
		{
sl@0
  1215
		case EWriteFlash:
sl@0
  1216
			{
sl@0
  1217
			return KMaxCrashLogSize; 
sl@0
  1218
			}
sl@0
  1219
		case EWriteComm:
sl@0
  1220
			{
sl@0
  1221
			return 0xFFFFFFFF;
sl@0
  1222
			}
sl@0
  1223
		default:
sl@0
  1224
			{
sl@0
  1225
			return 0;
sl@0
  1226
			}
sl@0
  1227
		} 
sl@0
  1228
	}
sl@0
  1229
sl@0
  1230
/**
sl@0
  1231
 * Records the offset in the flash partition where this crash begins
sl@0
  1232
 * @param aStart Offset in flash
sl@0
  1233
 */
sl@0
  1234
void SCMDataSave::SetCrashStartingPoint(TUint32 aStart)
sl@0
  1235
	{
sl@0
  1236
	iStartingPointForCrash = aStart;
sl@0
  1237
	}
sl@0
  1238
sl@0
  1239
//eof
sl@0
  1240