os/kernelhwsrv/kernel/eka/debug/crashMonitor/src/scmdatasave.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/scmdatasave.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1240 @@
     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\scmdatasave.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#define __INCLUDE_REG_OFFSETS__  // for SP_R13U in nk_plat.h
    1.22 +
    1.23 +#include <omap_dbg.h>
    1.24 +#include "arm_mem.h"
    1.25 +#include "nk_plat.h"
    1.26 +#include <omap_assp.h>
    1.27 +#include <scmonitor.h>
    1.28 +#include <scmdatasave.h> 
    1.29 +
    1.30 +/**
    1.31 + * @file
    1.32 + * @internal technology
    1.33 + */
    1.34 +
    1.35 +/**
    1.36 + * SCMDataSave constructor
    1.37 + * @param aMonitor - the monitor which has caught the syetem crash this object is saving data for 
    1.38 + * @param aFlash - the flash memory data will be written to, note the CrashFlash interface is
    1.39 + * 				   rather limited and does not support partial block writes
    1.40 + * @param aFlashInfo - data describing the structure of the flash data
    1.41 + */
    1.42 +EXPORT_C SCMDataSave::SCMDataSave(Monitor* aMonitor, CrashFlash* aFlash)
    1.43 +	: iMonitor(aMonitor)
    1.44 +		,iFlash(aFlash)
    1.45 +		,iByteCount(0)	
    1.46 +#ifdef SCM_COMM_OUTPUT	
    1.47 +		,iWriteSelect(EWriteComm)  // write data to debug port	
    1.48 +#else	
    1.49 +		,iWriteSelect(EWriteFlash)  // write data to flash
    1.50 +#endif
    1.51 +		,iPerformChecksum(ETrue)			 // checksum data 
    1.52 +		,iStartingPointForCrash(0)
    1.53 +	{  		
    1.54 +	const TInt KCacheSize = 128;
    1.55 +	iFlashCache = HBuf8::New(KCacheSize);
    1.56 +	CLTRACE1("(SCMDataSave) Creating writer with cache size = %d", KCacheSize);
    1.57 +	iWriter = new TCachedByteStreamWriter(const_cast<TUint8*>(iFlashCache->Ptr()), KCacheSize);
    1.58 +	iWriter->SetWriterImpl(this);
    1.59 +	}
    1.60 +
    1.61 +/**
    1.62 + * Destructor
    1.63 + */
    1.64 +SCMDataSave::~SCMDataSave()
    1.65 +	{
    1.66 +	delete iFlashCache;
    1.67 +	}
    1.68 +
    1.69 +/**
    1.70 + * Getter for the current byte count. This is the amount of data that has currently 
    1.71 + * been written to given media for this crash log
    1.72 + * @return The number of bytes written already to given media
    1.73 + */
    1.74 +TInt SCMDataSave::GetByteCount()
    1.75 +	{
    1.76 +	return iByteCount;
    1.77 +	}
    1.78 +
    1.79 +/**
    1.80 + * Logs the user stack for a given DThread object if it is available
    1.81 + * @param aThread - thread whose stack we wish to log
    1.82 + * @param aSizeDumped Holds the size of the data dumped
    1.83 + * @return one of the OS codes
    1.84 + */
    1.85 +TInt SCMDataSave::LogThreadUserStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
    1.86 +	{
    1.87 +	LOG_CONTEXT
    1.88 +	aSizeDumped = 0;
    1.89 +	TUint memDumped = 0;	
    1.90 +	
    1.91 +	TUint svSp, usrSp;
    1.92 +	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );	
    1.93 +	
    1.94 +	//first we check for a user stack...
    1.95 +	if (aThread->iUserStackRunAddress && aThread->iUserStackSize)
    1.96 +		{		
    1.97 +		//Get data together
    1.98 +		TThreadStack usrStack;
    1.99 +		usrStack.iStackType = TThreadStack::EUsrStack;
   1.100 +		usrStack.iThreadId = (TUint64)aThread->iId;					
   1.101 +				
   1.102 +		//map in the user stack
   1.103 +		TUint8* usrStart = (TUint8*)iMonitor->MapAndLocateUserStack(aThread); //What about Demand paging??
   1.104 +		TUint8* usrEnd = (TUint8*)(usrStart + aThread->iUserStackSize);
   1.105 +		if(usrStart) 
   1.106 +			{
   1.107 +			TUint8* stackPointer = (TUint8*)usrSp;			
   1.108 +			
   1.109 +			//check the stack pointer is in the range of the stack...
   1.110 +			if (stackPointer < usrStart || stackPointer >= usrEnd)
   1.111 +				{
   1.112 +				stackPointer = usrStart;
   1.113 +				}
   1.114 +			
   1.115 +			//log the size of the stack we are dumping
   1.116 +			usrStack.iStackSize = aFullStack || (stackPointer == usrStart) ? usrEnd - usrStart : usrEnd - stackPointer;
   1.117 +			TUint8* dumpFrom = aFullStack ? usrStart : stackPointer;
   1.118 +			
   1.119 +			//write the stack
   1.120 +			aSizeDumped+= usrStack.GetSize();
   1.121 +			usrStack.Serialize(*iWriter);					
   1.122 +			
   1.123 +			//now we dump the actual stack
   1.124 +			//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?
   1.125 +			//-1 because we dont want to write the byte at usrEnd			
   1.126 +			MTRAPD(memErr, LogMemory(dumpFrom, usrStack.iStackSize, aThread, memDumped));			
   1.127 +			if(KErrNone != memErr)
   1.128 +				{
   1.129 +				CLTRACE("Failed to log usr stack");
   1.130 +				}
   1.131 +			
   1.132 +			aSizeDumped+= memDumped;					
   1.133 +			}
   1.134 +		else
   1.135 +			{
   1.136 +			//write the struct
   1.137 +			aSizeDumped+=usrStack.GetSize();
   1.138 +			usrStack.Serialize(*iWriter);
   1.139 +			}
   1.140 +		}	
   1.141 +	return KErrNone;
   1.142 +	}
   1.143 +
   1.144 +/**
   1.145 + * Logs the supervisor stack for a given DThread object
   1.146 + * @param aThread - thread whose stack we wish to log
   1.147 + * @param aSizeDumped Holds the size of the data dumped
   1.148 + * @return one of the system wide codes
   1.149 + */
   1.150 +TInt SCMDataSave::LogThreadSupervisorStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
   1.151 +	{	
   1.152 +	LOG_CONTEXT
   1.153 +	aSizeDumped = 0;
   1.154 +	TUint memDumped;	
   1.155 +	
   1.156 +	TUint svSp, usrSp;
   1.157 +	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
   1.158 +	
   1.159 +	//now we dump the supervisor stack
   1.160 +	TThreadStack svrStack;
   1.161 +	svrStack.iStackType = TThreadStack::ESvrStack;
   1.162 +	svrStack.iThreadId = (TUint64)aThread->iId;
   1.163 +	
   1.164 +	if (aThread->iSupervisorStack && aThread->iSupervisorStackSize)
   1.165 +		{
   1.166 +		TUint8* svrStart = (TUint8*)aThread->iSupervisorStack;
   1.167 +		TUint8* svrEnd = (TUint8*)(svrStart + aThread->iSupervisorStackSize);
   1.168 +		TUint8* svrStackPointer = (TUint8*)svSp;
   1.169 +		
   1.170 +		//size of stack we are to dump
   1.171 +		svrStack.iStackSize = aFullStack || (svrStackPointer == svrStart) ? svrEnd - svrStart  : svrEnd - svrStackPointer;					
   1.172 +		
   1.173 +		if(svrStart)
   1.174 +			{
   1.175 +			//check the stack pointer is in the range of the stack...
   1.176 +			if (svrStackPointer < svrStart || svrStackPointer >= svrEnd)
   1.177 +				{
   1.178 +				svrStackPointer = svrStart;
   1.179 +				}
   1.180 +
   1.181 +			//write struct to flash
   1.182 +			aSizeDumped+=svrStack.GetSize();
   1.183 +			svrStack.Serialize(*iWriter);
   1.184 +			
   1.185 +			//now we dump the actual stack
   1.186 +			//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?
   1.187 +			MTRAPD(memErr, LogMemory(svrStart, svrStack.iStackSize, aThread, memDumped));
   1.188 +			aSizeDumped+=memDumped;
   1.189 +			
   1.190 +			if(KErrNone != memErr)
   1.191 +				{
   1.192 +				CLTRACE("Failed to log supervisor stack");
   1.193 +				}						
   1.194 +			}
   1.195 +		else
   1.196 +			{
   1.197 +			//write the struct
   1.198 +			aSizeDumped+=svrStack.GetSize();
   1.199 +			svrStack.Serialize(*iWriter);
   1.200 +			}
   1.201 +		}
   1.202 +	
   1.203 +	return KErrNone;
   1.204 +	}
   1.205 +
   1.206 +/**
   1.207 + * Takes a DProcess kernel object and logs its corrosponding code segments
   1.208 + * @param aProcess
   1.209 + * @param aSizeDumped Holds the size of the data dumped
   1.210 + * @return one of the OS wide error codes
   1.211 + */
   1.212 +TInt SCMDataSave::LogCodeSegments(DProcess* aProc, TUint& aSizeDumped)
   1.213 +	{	
   1.214 +	LOG_CONTEXT
   1.215 +	aSizeDumped = 0;	
   1.216 +	
   1.217 +	//the code segment set for this process
   1.218 +	TCodeSegmentSet segSet;
   1.219 +	segSet.iPid = (TUint64)aProc->iId;
   1.220 +	
   1.221 +	//make sure list mutex is ok
   1.222 +	if(Kern::CodeSegLock()->iHoldCount)
   1.223 +		{
   1.224 +		return KErrCorrupt;
   1.225 +		}
   1.226 +	
   1.227 +	//get code seg list
   1.228 +	SDblQue queue;		
   1.229 +	aProc->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
   1.230 +	
   1.231 +	//iterate through the list
   1.232 +	TInt codeSegCnt = 0;
   1.233 +	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
   1.234 +		{
   1.235 +		//get the code seg
   1.236 +		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
   1.237 +		
   1.238 +		if(codeSeg)
   1.239 +			{
   1.240 +			codeSegCnt++;
   1.241 +			}
   1.242 +		}
   1.243 +	
   1.244 +	if(codeSegCnt == 0)
   1.245 +		{
   1.246 +		return KErrNone;
   1.247 +		}	
   1.248 +	
   1.249 +	segSet.iNumSegs = codeSegCnt;
   1.250 +	segSet.Serialize(*iWriter);	
   1.251 +	aSizeDumped+=segSet.GetSize();
   1.252 +	
   1.253 +	TModuleMemoryInfo memoryInfo;
   1.254 +	
   1.255 +	//now we write each code segment
   1.256 +	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
   1.257 +		{
   1.258 +		//get the code seg
   1.259 +		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
   1.260 +		
   1.261 +		if(codeSeg)
   1.262 +			{			
   1.263 +			TCodeSegment seg;									
   1.264 +			seg.iXip = (codeSeg->iXIP) ? ETrue : EFalse;
   1.265 +			
   1.266 +			//Get the code seg type
   1.267 +			if(codeSeg->IsExe())
   1.268 +				{
   1.269 +				seg.iCodeSegType = EExeCodeSegType;
   1.270 +				}
   1.271 +			else if(codeSeg->IsDll())
   1.272 +				{
   1.273 +				seg.iCodeSegType = EDllCodeSegType;
   1.274 +				}
   1.275 +			
   1.276 +			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
   1.277 +			if(KErrNone == err)
   1.278 +				{
   1.279 +				seg.iCodeSegMemInfo = memoryInfo;
   1.280 +				}
   1.281 +			else
   1.282 +				{
   1.283 +				seg.iCodeSegMemInfo.iCodeSize = 0; 
   1.284 +
   1.285 +				// Still need to indicate it wasnt available somehow
   1.286 +				}
   1.287 +			
   1.288 +			//Get filename			
   1.289 +			seg.iNameLength = codeSeg->iFileName->Length();
   1.290 +			seg.iName = *(codeSeg->iFileName);
   1.291 +			
   1.292 +			aSizeDumped+=seg.GetSize();
   1.293 +			seg.Serialize(*iWriter);						
   1.294 +			}
   1.295 +		}
   1.296 +	
   1.297 +	//Empty this queue and clear marks
   1.298 +	DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
   1.299 +	
   1.300 +	return KErrNone;
   1.301 +	}
   1.302 +
   1.303 +/**
   1.304 + * This logs the rom version and header information to the crash media
   1.305 + * @param aSizeDumped amount of data occupied
   1.306 + * @return one of the OS wide codes
   1.307 + */
   1.308 +TInt SCMDataSave::LogRomInfo(TUint& aSizeDumped)	
   1.309 +	{
   1.310 +	aSizeDumped = 0;
   1.311 +	
   1.312 +	TRomHeaderData romData;
   1.313 +	
   1.314 +	TRomHeader rHdr = Epoc::RomHeader();
   1.315 +	
   1.316 +	romData.iMajorVersion = rHdr.iVersion.iMajor;
   1.317 +	romData.iMinorVersion = rHdr.iVersion.iMinor;
   1.318 +	romData.iBuildNumber = rHdr.iVersion.iBuild;
   1.319 +	romData.iTime = rHdr.iTime;
   1.320 +	
   1.321 +	TInt err = romData.Serialize(*iWriter);
   1.322 +	if(KErrNone != err)
   1.323 +		{
   1.324 +		return err;
   1.325 +		}
   1.326 +	
   1.327 +	aSizeDumped += romData.GetSize();
   1.328 +	
   1.329 +	return KErrNone;
   1.330 +	}
   1.331 +
   1.332 +/**
   1.333 + * Takes a DProcess kernel object and logs to flash
   1.334 + * @param aProc
   1.335 + * @param aSizeDumped Holds the size of the data dumped
   1.336 + * @return one of the OS wide error codes
   1.337 + */
   1.338 +TInt SCMDataSave::LogProcessData(DProcess* aProc, TUint& aSizeDumped)
   1.339 +	{	
   1.340 +	LOG_CONTEXT
   1.341 +	aSizeDumped = 0;	
   1.342 +	
   1.343 +	TProcessData procData;
   1.344 +	DCodeSeg* codeSeg = aProc->iCodeSeg;
   1.345 +
   1.346 +	procData.iPriority = aProc->iPriority;
   1.347 +	procData.iPid = (TUint64)aProc->iId;
   1.348 +	
   1.349 +	//the code segment is not always available
   1.350 +	if(codeSeg)
   1.351 +		{
   1.352 +		procData.iNamesize = codeSeg->iFileName->Length();
   1.353 +		procData.iName = *(codeSeg->iFileName);
   1.354 +		}
   1.355 +	
   1.356 +	aSizeDumped += procData.GetSize();
   1.357 +	procData.Serialize(*iWriter);
   1.358 +	
   1.359 +	return KErrNone;
   1.360 +	}
   1.361 +
   1.362 +/**
   1.363 + * Creates meta data about the crash such as time of crash, exit reason etc. to be logged
   1.364 + * later on when we have log size.
   1.365 + * @param aCategory - crash category
   1.366 + * @param aReason - crash reason
   1.367 + * @param aSizeDumped Holds the size of the data dumped
   1.368 + * @return one of the OS wide codes
   1.369 + */
   1.370 +TInt SCMDataSave::LogCrashHeader(const TDesC8& aCategory, TInt aReason, TInt aCrashId, TUint& aSizeDumped)
   1.371 +	{
   1.372 +	LOG_CONTEXT
   1.373 +	aSizeDumped = 0;
   1.374 +	
   1.375 +	//the thread that crashed is the context in which we are running
   1.376 +	DThread* crashedThread = &Kern::CurrentThread();
   1.377 +	
   1.378 +	iCrashInf.iPid = crashedThread->iOwningProcess->iId; 
   1.379 +	iCrashInf.iTid = crashedThread->iId;
   1.380 +	iCrashInf.iCrashTime = CrashTime();
   1.381 +	iCrashInf.iExitType = 0; // Not yet done: Exception or Fault - should be in category
   1.382 +	iCrashInf.iExitReason = aReason;
   1.383 +	iCrashInf.iFlashAlign = KFlashAlignment; //record the flash alignment (word aligned for now)
   1.384 +	iCrashInf.iCachedWriterSize = iWriter->GetCacheSize();
   1.385 +	
   1.386 +	iCrashInf.iCategorySize = aCategory.Length();
   1.387 +	iCrashInf.iCategory = aCategory;	
   1.388 +	iCrashInf.iCrashId = aCrashId;
   1.389 +	
   1.390 +	iCrashInf.iFlashBlockSize = KCrashLogBlockSize;;
   1.391 +	iCrashInf.iFlashPartitionSize = KCrashLogSize;;
   1.392 +	
   1.393 +	TSuperPage& sp=Kern::SuperPage();
   1.394 +	iCrashInf.iExcCode = sp.iKernelExcId;
   1.395 +
   1.396 +	//These will be updated with more info at end of crash
   1.397 +	aSizeDumped+=iCrashInf.GetSize();
   1.398 +	iCrashInf.Serialize(*iWriter);
   1.399 +	
   1.400 +	aSizeDumped+=iHdr.GetSize();
   1.401 +	iHdr.Serialize(*iWriter);		
   1.402 +
   1.403 +	CLTRACE1("(SCMDataSave::LogCrashHeader) finished bytes written= %d", iWriter->GetBytesWritten());
   1.404 +	return KErrNone;
   1.405 +	}
   1.406 +
   1.407 +/**
   1.408 + * Logs meta data about a given DThread object
   1.409 + * @param aThread Thread to dump
   1.410 + * @param aSizeDumped Holds the size of the data dumped
   1.411 + * @return
   1.412 + */
   1.413 +TInt SCMDataSave::LogThreadData(DThread* aThread, TUint& aSizeDumped)
   1.414 +	{
   1.415 +	LOG_CONTEXT
   1.416 +	aSizeDumped = 0;	
   1.417 +	
   1.418 +	//struct to hold data that gets written to flash
   1.419 +	TThreadData threadData;
   1.420 +	
   1.421 +	threadData.iTid = (TUint64)aThread->iId;
   1.422 +	threadData.iOwnerId = (TUint64)aThread->iOwningProcess->iId;
   1.423 +	threadData.iPriority = aThread->iThreadPriority;
   1.424 +	
   1.425 +	//Get the stack pointers	
   1.426 +	TUint svSp, usrSp;
   1.427 +	iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
   1.428 +	threadData.iUsrSP = usrSp;
   1.429 +	threadData.iSvcSP = svSp;
   1.430 +		
   1.431 +	//supervisor and user stack details
   1.432 +	threadData.iSvcStack = (TInt32)aThread->iSupervisorStack;
   1.433 +	threadData.iSvcStacksize = aThread->iSupervisorStackSize;
   1.434 +	threadData.iUsrStack = aThread->iUserStackRunAddress;
   1.435 +	threadData.iUsrStacksize = aThread->iUserStackSize;	
   1.436 +	
   1.437 +	//currently we can only get the kernels heap
   1.438 +	if(aThread == &Kern::CurrentThread())
   1.439 +		{
   1.440 +		TInt32 heapLoc = 0;
   1.441 +		TInt32 heapSz = 0;
   1.442 +		TInt err = FindKernelHeap(heapLoc,heapSz);
   1.443 +		if(KErrNone == err)
   1.444 +			{
   1.445 +			threadData.iSvcHeap = heapLoc;
   1.446 +			threadData.iSvcHeapSize = heapSz;
   1.447 +			}
   1.448 +		else
   1.449 +			{
   1.450 +			CLTRACE("\tError: Unable to get kernel heap");
   1.451 +			}
   1.452 +		}	
   1.453 +	
   1.454 +	//get filename	
   1.455 +	TFileName filename;
   1.456 +	aThread->TraceAppendFullName(filename, EFalse);
   1.457 +	
   1.458 +	threadData.iName.Copy(filename);
   1.459 +	threadData.iNamesize = threadData.iName.Length();
   1.460 +	
   1.461 +		
   1.462 +#ifdef __INCLUDE_NTHREADBASE_DEFINES__
   1.463 +	threadData.iLastCpu = aThread->iNThread.iLastCpu;
   1.464 +#else	
   1.465 +	threadData.iLastCpu = aThread->iNThread.iSpare3;	
   1.466 +#endif	
   1.467 +	
   1.468 +	threadData.Serialize(*iWriter);
   1.469 +	aSizeDumped+=threadData.GetSize();
   1.470 +	
   1.471 +	return KErrNone;
   1.472 +	}
   1.473 +
   1.474 +/**
   1.475 + * Logs the arm exception stacks 
   1.476 + * @param aSizeDumped Holds the size of the data dumped 
   1.477 + * @return one of the OS wide codes
   1.478 + */
   1.479 +TInt SCMDataSave::LogExceptionStacks(TUint& aSizeDumped)
   1.480 +	{
   1.481 +	LOG_CONTEXT
   1.482 +	aSizeDumped = 0;
   1.483 +	TUint memDumped = 0;
   1.484 +	
   1.485 +	#if defined(__EPOC32__) && !defined(__CPU_X86)
   1.486 +
   1.487 +	TStackInfo& stackInfo = Kern::SuperPage().iStackInfo;
   1.488 +
   1.489 +	TThreadStack irqStack;
   1.490 +	irqStack.iStackType = TThreadStack::EIRQStack;
   1.491 +	irqStack.iStackSize = stackInfo.iIrqStackSize;
   1.492 +	
   1.493 +	aSizeDumped+=irqStack.GetSize();
   1.494 +	irqStack.Serialize(*iWriter);
   1.495 +	
   1.496 +	//now dump the IRQ memory - not much we can do in the event of an error
   1.497 +	MTRAPD(irqErr, LogMemory((TUint8*)stackInfo.iIrqStackBase, stackInfo.iIrqStackSize, &Kern::CurrentThread(), memDumped));	
   1.498 +	
   1.499 +	if(KErrNone != irqErr)
   1.500 +		{
   1.501 +		CLTRACE("*****Failed to log IRQ stack");
   1.502 +		}
   1.503 +	aSizeDumped+=memDumped;
   1.504 +	
   1.505 +	//Next, we do the FIQ stack
   1.506 +	TThreadStack fiqStack;
   1.507 +	fiqStack.iStackType = TThreadStack::EFIQStack;
   1.508 +	fiqStack.iStackSize = stackInfo.iFiqStackSize;
   1.509 +	
   1.510 +	aSizeDumped+=fiqStack.GetSize();
   1.511 +	fiqStack.Serialize(*iWriter);
   1.512 +	
   1.513 +	//Now dump the stack itself
   1.514 +	MTRAPD(fiqErr, LogMemory((TUint8*)stackInfo.iFiqStackBase, stackInfo.iFiqStackSize, &Kern::CurrentThread(), memDumped));
   1.515 +	
   1.516 +	if(KErrNone != fiqErr )
   1.517 +		{
   1.518 +		CLTRACE("*****Failed to log FIQ stack");
   1.519 +		}
   1.520 +	aSizeDumped+=memDumped;
   1.521 +
   1.522 +	#endif
   1.523 +	
   1.524 +	return KErrNone;
   1.525 +	}
   1.526 +
   1.527 +/**
   1.528 + * Logs the CPU Registers at the time of crash
   1.529 + * @param aSizeDumped Holds the size of the data dumped
   1.530 + * @return system wide OS code
   1.531 + */
   1.532 +TInt SCMDataSave::LogCPURegisters(TUint& aSizeDumped)
   1.533 +	{
   1.534 +	LOG_CONTEXT
   1.535 +	aSizeDumped = 0;
   1.536 +	
   1.537 +	TInt32 fullSet = 37;
   1.538 +	
   1.539 +	//meta data about the thread set
   1.540 +	TRegisterSet threadSet;
   1.541 +	threadSet.iNumRegisters = fullSet;
   1.542 +	
   1.543 +	aSizeDumped+=threadSet.GetSize();
   1.544 +	threadSet.Serialize(*iWriter);
   1.545 +		
   1.546 +	SFullArmRegSet regSet;
   1.547 +	ReadCPURegisters(regSet);
   1.548 +	TArmReg* regs = (TArmReg*)&regSet;
   1.549 +		
   1.550 +	TInt32 cnt = 0;
   1.551 +	for(cnt = 0; cnt < fullSet; cnt++)
   1.552 +		{			
   1.553 +		//this is the struct to store the register value in
   1.554 +		TRegisterValue regVal;
   1.555 +		regVal.iType = cnt * 0x100;
   1.556 +		regVal.iValue32 = regs[cnt];
   1.557 +		regVal.iOwnId = Kern::CurrentThread().iId;
   1.558 +		
   1.559 +		aSizeDumped+=regVal.GetSize();
   1.560 +		regVal.Serialize(*iWriter);
   1.561 +		}
   1.562 +
   1.563 +	return KErrNone;	
   1.564 +	}
   1.565 +
   1.566 +/**
   1.567 + * This logs the registers for a given thread to the flash memory
   1.568 + * @param aThread - thread whose registers we want
   1.569 + * @param aRegType - type of register set required such as user, supervisor etc
   1.570 + * @param aSizeDumped Holds the size of the data dumped
   1.571 + * @return one of the OS return codes
   1.572 + */
   1.573 +TInt SCMDataSave::LogRegisters(DThread* aThread, const TRegisterSetType& aRegType, TUint& aSizeDumped)
   1.574 +	{
   1.575 +	LOG_CONTEXT
   1.576 +	aSizeDumped = 0;
   1.577 +	
   1.578 +	TArmRegSet regs;
   1.579 +	TUint32 availableRegs;
   1.580 +	TInt err;
   1.581 +	
   1.582 +	//for the current thread we do things differently
   1.583 +	if(aThread == &Kern::CurrentThread() && aRegType == EFullCPURegisters)
   1.584 +		{
   1.585 +		err = LogCPURegisters(aSizeDumped);
   1.586 +		return err;
   1.587 +		} 
   1.588 +	else if(aThread == &Kern::CurrentThread())
   1.589 +		{
   1.590 +		//only do full cpu reg for the current thread
   1.591 +		return KErrNotSupported;
   1.592 +		}
   1.593 +	
   1.594 +	//Read the appropriate registers
   1.595 +	switch(aRegType)
   1.596 +		{
   1.597 +		case EUserRegisters :
   1.598 +			{
   1.599 +			err = ReadUserRegisters(aThread, regs, availableRegs);
   1.600 +			break;
   1.601 +			}
   1.602 +		case ESupervisorRegisters :
   1.603 +			{
   1.604 +			err = ReadSystemRegisters(aThread, regs, availableRegs);
   1.605 +			break;			
   1.606 +			}
   1.607 +		default : return KErrNotSupported;
   1.608 +		}
   1.609 +	
   1.610 +	if(err != KErrNone)
   1.611 +		{
   1.612 +		return err;
   1.613 +		}	
   1.614 +		
   1.615 +	//meta data about the thread set
   1.616 +	TRegisterSet threadSet;
   1.617 +	
   1.618 +	//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
   1.619 +	TUint numR = 0;
   1.620 +	for(TInt cnt =0; cnt< 8*sizeof(availableRegs); cnt++) //cycle through 1 bit at a time
   1.621 +		{
   1.622 +		if(0x1 & (availableRegs>>cnt))
   1.623 +			numR++;
   1.624 +		}
   1.625 +	
   1.626 +	threadSet.iNumRegisters = numR;
   1.627 +	
   1.628 +	if(numR == 0)
   1.629 +		return KErrNone;
   1.630 +	
   1.631 +	threadSet.Serialize(*iWriter);
   1.632 +	aSizeDumped += threadSet.GetSize();
   1.633 +	
   1.634 +	TInt32 currentRegister = 1;
   1.635 +	TArmReg* reg = (TArmReg*)(&regs);	
   1.636 +	
   1.637 +	for(TInt32 cnt = 0; cnt < KArmRegisterCount; cnt++)
   1.638 +		{		
   1.639 +		//look at the unavailable bitmask to see current register is available
   1.640 +		//only write the registers we have values for
   1.641 +		if(currentRegister & availableRegs)
   1.642 +			{
   1.643 +			//this is the struct to store the register value in
   1.644 +			TRegisterValue regVal;
   1.645 +						
   1.646 +			//get register type as per symbian elf docs
   1.647 +			TUint32 registerType;
   1.648 +			err = GetRegisterType(aRegType, cnt, registerType);
   1.649 +			if(err != KErrNone)
   1.650 +				{
   1.651 +				continue;
   1.652 +				}
   1.653 +			regVal.iType = registerType;
   1.654 +			regVal.iOwnId = aThread->iId;
   1.655 +			
   1.656 +			//set value
   1.657 +			regVal.iValue32 = reg[cnt];
   1.658 +			
   1.659 +			aSizeDumped+=regVal.GetSize();
   1.660 +			regVal.Serialize(*iWriter);
   1.661 +			}
   1.662 +		
   1.663 +		currentRegister<<=1; 
   1.664 +		}
   1.665 +	
   1.666 +	return KErrNone;
   1.667 +	}
   1.668 +
   1.669 +/**
   1.670 + * This logs memory in the specified area
   1.671 + * @param aStartAddress - address to start from
   1.672 + * @param aEndAddress - address to finish
   1.673 + * @param aThread - process whose memory this is in
   1.674 + * @param aSizeDumped Holds the size of the data dumped
   1.675 + * @return one of the system wide codes
   1.676 + */
   1.677 +TInt SCMDataSave::LogMemory(const TUint8* aStartAddress, TInt aLength, const DThread* aThread, TUint& aSizeDumped)
   1.678 +	{
   1.679 +	LOG_CONTEXT
   1.680 +	aSizeDumped = 0;	
   1.681 +	
   1.682 +	if(aThread->iOwningProcess != &Kern::CurrentProcess())
   1.683 +		{
   1.684 +		TInt err = iMonitor->SwitchAddressSpace(aThread->iOwningProcess, ETrue);
   1.685 +		if(KErrNone != err)
   1.686 +			{
   1.687 +			return err;
   1.688 +			}
   1.689 +		}
   1.690 +	
   1.691 +	TMemoryDump memDump;
   1.692 +	memDump.iStartAddress = (TUint32)aStartAddress;
   1.693 +	memDump.iLength = aLength;
   1.694 +	memDump.iPid = aThread->iOwningProcess->iId;
   1.695 +	
   1.696 +	aSizeDumped+=memDump.GetSize();
   1.697 +	memDump.Serialize(*iWriter);	
   1.698 +	
   1.699 +	if(!aStartAddress)
   1.700 +		{
   1.701 +		return KErrArgument;
   1.702 +		}
   1.703 +	
   1.704 +	TRawData theMemory;
   1.705 +	theMemory.iData.Set(const_cast<TUint8*>(aStartAddress), aLength, aLength);
   1.706 +	
   1.707 +	theMemory.Serialize(*iWriter);
   1.708 +	aSizeDumped+=theMemory.GetSize();
   1.709 +	
   1.710 +	return KErrNone;	
   1.711 +	}
   1.712 +
   1.713 +/**
   1.714 + * This logs the locks held by system at time of crash
   1.715 + * @param aSizeDumped Holds the size of the data dumped
   1.716 + * @return one of the system wide codes
   1.717 + */
   1.718 +TInt SCMDataSave::LogLocks(TUint& aSizeDumped)
   1.719 +	{
   1.720 +	LOG_CONTEXT
   1.721 +	aSizeDumped = 0;
   1.722 +	
   1.723 +	// get the mutex logs & waits & log via a TLockData object		
   1.724 +	TSCMLockData lockData;
   1.725 +
   1.726 +	const TInt KMaxLockCheck = 20; // so no possibility of infinite loop
   1.727 +		
   1.728 +	TInt lockCount = 0;
   1.729 +	// check for kernel locks - 	
   1.730 +	for(TInt i=0;i<KMaxLockCheck;i++)
   1.731 +		{		
   1.732 +		TBool locked = NKern::KernelLocked(i);	
   1.733 +		if(!locked)
   1.734 +			{
   1.735 +			lockData.SetLockCount(lockCount);
   1.736 +			break;		
   1.737 +			}
   1.738 +		// found a valid lock for value i increment the clock counter
   1.739 +		lockCount++;
   1.740 +		}
   1.741 +	
   1.742 +	// now mutexes
   1.743 +	DMutex* mutex = Kern::CodeSegLock();
   1.744 +	if(mutex)
   1.745 +		{
   1.746 +		lockData.SetMutexHoldCount(mutex->iHoldCount);
   1.747 +		lockData.SetMutexThreadWaitCount(mutex->iWaitCount);
   1.748 +		}
   1.749 +	else
   1.750 +		{
   1.751 +		// no mutex held set to -1
   1.752 +		lockData.SetMutexHoldCount(0);
   1.753 +		lockData.SetMutexThreadWaitCount(0);		
   1.754 +		}
   1.755 +
   1.756 +	aSizeDumped+=lockData.GetSize();
   1.757 +	TInt err = lockData.Serialize(*iWriter);
   1.758 +	
   1.759 +	return err;
   1.760 +	}
   1.761 +
   1.762 +/**
   1.763 + * Writes the SCM Configuration to the start of the media
   1.764 + * @param aScmConfig Configuration to write
   1.765 + * @return one of the system wide codes
   1.766 + */
   1.767 +TInt SCMDataSave::LogConfig(SCMConfiguration& aScmConfig)
   1.768 +	{
   1.769 +	iWriter->SetPosition(0);
   1.770 +	
   1.771 +	TInt err = aScmConfig.Serialize(*iWriter);
   1.772 +	
   1.773 +	if( err != KErrNone)
   1.774 +		{
   1.775 +		CLTRACE1("SCMDataSave::LogConfig failed err = %d", err);
   1.776 +		}
   1.777 +
   1.778 +	return err;
   1.779 +	}
   1.780 +
   1.781 +/**
   1.782 + * Reads the SCM Configuration from the media
   1.783 + * @param aScmConfig
   1.784 + * @return one of the system wide codes
   1.785 + */
   1.786 +TInt SCMDataSave::ReadConfig(SCMConfiguration& aScmConfig)
   1.787 +	{		
   1.788 +	const TInt KBufSize = 135; //Not yet done: Put in header, beside config defn
   1.789 +
   1.790 +	if( KBufSize < aScmConfig.GetSize())
   1.791 +		{
   1.792 +		CLTRACE2("(SCMDataSave::ReadConfig) ** ERROR Inadequate buffer actual = %d req = %d"
   1.793 +				, KBufSize,  aScmConfig.GetSize());	
   1.794 +		}
   1.795 +	
   1.796 +	// try and read the configuration
   1.797 +	TBuf8<KBufSize> buf;
   1.798 +	buf.SetLength(KBufSize);
   1.799 +		
   1.800 +	iFlash->SetReadPos(0); // config always at 0
   1.801 +	iFlash->Read(buf);
   1.802 +	 
   1.803 +	TByteStreamReader reader(const_cast<TUint8*>(buf.Ptr()));		
   1.804 +	TInt err = aScmConfig.Deserialize(reader);	
   1.805 +	if(err == KErrNotReady)
   1.806 +		{
   1.807 +		CLTRACE("(SCMDataSave::ReadConfig) no config saved - use default");
   1.808 +		}	
   1.809 +	else if(err == KErrNone)	
   1.810 +		{
   1.811 +		CLTRACE("(SCMDataSave::ReadConfig) Config read ok"); 		
   1.812 +		}
   1.813 +	else
   1.814 +		{
   1.815 +		CLTRACE1("(SCMDataSave::ReadConfig) error reading config err = %d", err); 
   1.816 +		}
   1.817 +	
   1.818 +	return err;
   1.819 +	}
   1.820 +
   1.821 +/**
   1.822 + * This is a look up table to map the register type and number to the symbian elf definition 
   1.823 + * of register type
   1.824 + * @param aSetType this is the register set type - user, supervisor etc
   1.825 + * @param aRegNumber this is the number of the register as per TArmRegisters in arm_types.h
   1.826 + * @param aSizeDumped Holds the size of the data dumped
   1.827 + * @return One of the OS wide codes
   1.828 + */
   1.829 +TInt SCMDataSave::GetRegisterType(const TRegisterSetType& aSetType, TInt32& aRegNumber, TUint32& aRegisterType)
   1.830 +	{	
   1.831 +	//validate arguments
   1.832 +	if(aRegNumber < EArmR0 || aRegNumber > EArmFlags)
   1.833 +		{
   1.834 +		return KErrArgument;
   1.835 +		}
   1.836 +	
   1.837 +	//look at what type we are using
   1.838 +	switch(aSetType)
   1.839 +		{
   1.840 +		case EUserRegisters :
   1.841 +			{
   1.842 +			aRegisterType = aRegNumber * 0x100; //for R0 to R16 (CPSR) it just increments in 0x100 from 0x0 to 0x1000
   1.843 +			break;
   1.844 +			}
   1.845 +		case ESupervisorRegisters :
   1.846 +			{
   1.847 +			//same as EUserRegisters except R13 and R14 are different
   1.848 +			if(aRegNumber == EArmSp)
   1.849 +				{
   1.850 +				aRegisterType = 0x1100;
   1.851 +				break;
   1.852 +				}
   1.853 +			else if(aRegNumber == EArmLr)
   1.854 +				{
   1.855 +				aRegisterType = 0x1200;
   1.856 +				break;
   1.857 +				}
   1.858 +			else
   1.859 +				{
   1.860 +				aRegisterType = aRegNumber * 0x100;
   1.861 +				break;
   1.862 +				}		
   1.863 +			}
   1.864 +		default : return KErrNotSupported;
   1.865 +		}
   1.866 +	
   1.867 +	return KErrNone;
   1.868 +	}
   1.869 +
   1.870 +/**
   1.871 + * Writes the trace buffer to the crash log. 
   1.872 + * @param aSizeToDump Number of bytes to dump. If this is zero we attempt to write the entire buffer
   1.873 + * @param aSizeDumped Holds the size of the data dumped
   1.874 + * @return One of the OS wide codes
   1.875 + */
   1.876 +TInt SCMDataSave::LogTraceBuffer(TInt aSizeToDump, TUint& aSizeDumped)
   1.877 +	{
   1.878 +	LOG_CONTEXT
   1.879 +	aSizeDumped = 0;
   1.880 +	TUint memDumped = 0;
   1.881 +	
   1.882 +	TBool dumpAll = (aSizeToDump == 0) ? ETrue : EFalse;
   1.883 +	
   1.884 +	//Because the btrace buffer is a circular one, we need to save it in two parts
   1.885 +	//this corrosponds to how we read it	
   1.886 +	TUint8* data;
   1.887 +	TUint sizeOfPartRead;
   1.888 +	TInt spaceRemaining = aSizeToDump;
   1.889 +	
   1.890 +	//This structure will be filled after the first pass and cached so by the time we ARE writing it will
   1.891 +	//contain the data we want 
   1.892 +	aSizeDumped+=iTrace.GetSize();
   1.893 +	iTrace.Serialize(*iWriter);
   1.894 +	
   1.895 +	//read first part
   1.896 +	TInt err = BTrace::Control(BTrace::ECtrlCrashReadFirst,&data,&sizeOfPartRead);
   1.897 +	
   1.898 +	while(KErrNone == err && sizeOfPartRead > 0)
   1.899 +		{
   1.900 +		TUint rawSize = 0; //how much of this read data want we to dump
   1.901 +		
   1.902 +		if(dumpAll)
   1.903 +			{
   1.904 +			rawSize = sizeOfPartRead;
   1.905 +			}
   1.906 +		else	//Otherwise see what room is left for dumpage
   1.907 +			{
   1.908 +			rawSize  = ((sizeOfPartRead + iTrace.iSizeOfMemory) > aSizeToDump) ? spaceRemaining : sizeOfPartRead;
   1.909 +			}		
   1.910 +		
   1.911 +		//Only relevant if restricting the dump
   1.912 +		if(spaceRemaining <= 0 && !dumpAll)
   1.913 +			break;
   1.914 +		
   1.915 +		TPtrC8 ptr(data, rawSize);
   1.916 +		err = LogRawData(ptr, memDumped);
   1.917 +		if(KErrNone != err)
   1.918 +			{
   1.919 +			CLTRACE1("Logging Raw data failed - [%d]", err);
   1.920 +			err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
   1.921 +			continue;
   1.922 +			}
   1.923 +		
   1.924 +		aSizeDumped+=memDumped;
   1.925 +		
   1.926 +		iTrace.iSizeOfMemory += rawSize;
   1.927 +		iTrace.iNumberOfParts++;
   1.928 +		spaceRemaining -= rawSize;		
   1.929 +		
   1.930 +		err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
   1.931 +		}
   1.932 +	
   1.933 +	return KErrNone;
   1.934 +	}
   1.935 +
   1.936 +/**
   1.937 + * Logs the data in a TRawData struct
   1.938 + * @param aData 
   1.939 + * @param aSizeDumped Holds the size of the data dumped
   1.940 + * @return One of the OS wide codes
   1.941 + */
   1.942 +TInt SCMDataSave::LogRawData(const TDesC8& aData, TUint& aSizeDumped)
   1.943 +	{
   1.944 +	TRawData theData;
   1.945 +	theData.iLength = aData.Length();
   1.946 +	theData.iData.Set(const_cast<TUint8*>(aData.Ptr()), aData.Length(), aData.Length());
   1.947 +	
   1.948 +	aSizeDumped+=theData.GetSize();
   1.949 +	return theData.Serialize(*iWriter);	
   1.950 +	}
   1.951 +
   1.952 +
   1.953 +/**
   1.954 + * Logs the kernels heap and returns the size dumped via aSizeDumped
   1.955 + * @param aSizeDumped Holds the size of the data dumped
   1.956 + * @return
   1.957 + */
   1.958 +TInt SCMDataSave::LogKernelHeap(TUint& aSizeDumped)
   1.959 +	{
   1.960 +	LOG_CONTEXT
   1.961 +	
   1.962 +	TInt32 heapLoc = 0;
   1.963 +	TInt32 heapSize = 0;
   1.964 +	TInt32 err = FindKernelHeap(heapLoc, heapSize);
   1.965 +	if(KErrNone == err)
   1.966 +		{
   1.967 +		return LogMemory((TUint8*)heapLoc, heapSize, &Kern::CurrentThread(), aSizeDumped);
   1.968 +		}
   1.969 +	
   1.970 +	CLTRACE1("\tCouldnt find the kernel heap: [%d]", err);
   1.971 +	return err;
   1.972 +	}
   1.973 +
   1.974 +/**
   1.975 + * Iterates the object containers and finds the kernel heap
   1.976 + * @param aHeapLocation Contains the memory location of the kernel heap
   1.977 + * @param aHeapSize Contains the size of the Heap
   1.978 + * @return One of the OS wide codes
   1.979 + */
   1.980 +TInt SCMDataSave::FindKernelHeap(TInt32& aHeapLocation, TInt32& aHeapSize)
   1.981 +	{
   1.982 +	LOG_CONTEXT
   1.983 +	
   1.984 +	//Get Chunk object container
   1.985 +	DObjectCon* objectContainer = Kern::Containers()[EChunk];
   1.986 +	if(objectContainer == NULL)
   1.987 +		{		
   1.988 +		CLTRACE("\tFailed to get object container for the chunks");
   1.989 +		return KErrNotFound;
   1.990 +		}
   1.991 +	
   1.992 +	//Must check the mutex on this is ok otherwise the data will be in an inconsistent state
   1.993 +	if(objectContainer->Lock()->iHoldCount)
   1.994 +		{
   1.995 +		CLTRACE("\tChunk Container is in an inconsistant state");
   1.996 +		return KErrCorrupt;
   1.997 +		}
   1.998 +	
   1.999 +	TInt numObjects = objectContainer->Count();	
  1.1000 +	
  1.1001 +	for(TInt cnt = 0; cnt< numObjects; cnt ++)
  1.1002 +		{		
  1.1003 +		DChunk* candidateHeapChunk = (DChunk*)(*objectContainer)[cnt];
  1.1004 +		
  1.1005 +		//Get the objects name
  1.1006 +		TBuf8<KMaxKernelName> name;
  1.1007 +		candidateHeapChunk->TraceAppendFullName(name,EFalse);
  1.1008 +		
  1.1009 +		if(name == KKernelHeapChunkName)
  1.1010 +			{
  1.1011 +			#ifndef __MEMMODEL_FLEXIBLE__
  1.1012 +				aHeapLocation = (TInt32)candidateHeapChunk->iBase;
  1.1013 +			#else
  1.1014 +				aHeapLocation = (TInt32)candidateHeapChunk->iFixedBase;
  1.1015 +			#endif
  1.1016 +				
  1.1017 +				aHeapSize = candidateHeapChunk->iSize;
  1.1018 +				
  1.1019 +			return KErrNone;
  1.1020 +			}
  1.1021 +		}
  1.1022 +	
  1.1023 +	return KErrNotFound;
  1.1024 +	}
  1.1025 +
  1.1026 +/**
  1.1027 + * This logs the variant specific descriptor data to the crash log
  1.1028 + * @param aSizeDumped records how much was dumped by this function
  1.1029 + * @return one of the OS wide codes
  1.1030 + */
  1.1031 +TInt SCMDataSave::LogVariantSpecificData(TUint& aSizeDumped)
  1.1032 +	{
  1.1033 +	LOG_CONTEXT
  1.1034 +	
  1.1035 +	aSizeDumped = 0;
  1.1036 +	
  1.1037 +	//Change this descriptor as required for your needs
  1.1038 +	_LIT(KVariantSpecificData, "This is the variant specific data. Put your own here");
  1.1039 +	
  1.1040 +	TVariantSpecificData varData;
  1.1041 +	varData.iSize = KVariantSpecificData().Size(); 
  1.1042 +	
  1.1043 +	TInt err = varData.Serialize(*iWriter);
  1.1044 +	if(KErrNone != err)
  1.1045 +		{
  1.1046 +		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
  1.1047 +		return err;
  1.1048 +		}
  1.1049 +	aSizeDumped+=varData.GetSize();
  1.1050 +	
  1.1051 +	TUint rawDataSize = 0;
  1.1052 +	err = LogRawData(KVariantSpecificData(), rawDataSize);
  1.1053 +	if(KErrNone != err)
  1.1054 +		{
  1.1055 +		CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
  1.1056 +		return err;
  1.1057 +		}
  1.1058 +	
  1.1059 +	aSizeDumped+=rawDataSize;
  1.1060 +	
  1.1061 +	return KErrNone;
  1.1062 +	}
  1.1063 +
  1.1064 +
  1.1065 +/**
  1.1066 + * This method is the callback used by MPhysicalWriterImpl interface
  1.1067 + * if the TCachedByteStreamWriter is configured to use this interface
  1.1068 + * the callback avoids the need for temp buffers & can interface directly with the
  1.1069 + * flash writer methods
  1.1070 + * @param aData - data to write
  1.1071 + * @param aLen	- length of data to write
  1.1072 + * @param aPos  - writers internal position   
  1.1073 + */
  1.1074 +void SCMDataSave::DoPhysicalWrite(TAny* aData, TInt aPos, TInt aLen)
  1.1075 +	{	
  1.1076 +	if(iPerformChecksum)
  1.1077 +		{
  1.1078 +		iChecksum.ChecksumBlock((TUint8*)aData, aLen);
  1.1079 +		}
  1.1080 +	
  1.1081 +	if( this->iWriteSelect == EWriteComm)
  1.1082 +		{	
  1.1083 +		WriteUart((TUint8*)aData, aLen);		
  1.1084 +		}
  1.1085 +	else  // EWriteFlash
  1.1086 +		{			
  1.1087 +		Write(aData, aLen);
  1.1088 +		}
  1.1089 +	}
  1.1090 +
  1.1091 +/**
  1.1092 + * Writes data to Flash
  1.1093 + * @param aSomething Pointer to the data
  1.1094 + * @param aSize Size of the data
  1.1095 + */
  1.1096 +void SCMDataSave::Write(const TAny* aSomething, TInt aSize)
  1.1097 +	{		
  1.1098 +	TPtrC8 data((const TUint8 *)aSomething, aSize);
  1.1099 +	
  1.1100 +	TInt written = 0;
  1.1101 +	
  1.1102 +	WriteCrashFlash(iByteCount, written, data);
  1.1103 +	iByteCount+= written;	
  1.1104 +	}
  1.1105 +
  1.1106 +/**
  1.1107 + * Writes a descriptor to the crash flash
  1.1108 + * @param aPos Position in flash to write
  1.1109 + * @param aSize Holds the size of the data written after the call
  1.1110 + * @param aBuffer Descriptor to write
  1.1111 + */
  1.1112 +void SCMDataSave::WriteCrashFlash(TInt aPos, TInt& aSize, const TDesC8& aBuffer)
  1.1113 +	{	
  1.1114 +	//Set write position in the flash
  1.1115 +	iFlash->SetWritePos(aPos);	
  1.1116 +	iFlash->Write(aBuffer);
  1.1117 +	
  1.1118 +	//get bytes written
  1.1119 +	aSize += iFlash->BytesWritten();
  1.1120 +	
  1.1121 +	if(aSize != aBuffer.Length())
  1.1122 +		{
  1.1123 +		CLTRACE2("(SCMDataSave::WriteCrashFlash) Over the limit aSize = %d aBuffer.Length() = %d",
  1.1124 +				aSize,  aBuffer.Length());
  1.1125 +		}
  1.1126 +	}
  1.1127 +	
  1.1128 +/**
  1.1129 + * Writes a descriptor via serial
  1.1130 + * @param aDes Descriptor to write
  1.1131 + */
  1.1132 +void SCMDataSave::WriteUart(const TDesC8& aDes)
  1.1133 +	{
  1.1134 +	WriteUart(aDes.Ptr(), aDes.Length());	
  1.1135 +	}
  1.1136 +
  1.1137 +/**
  1.1138 + * Writes data via serial
  1.1139 + * @param aData Data to write
  1.1140 + * @param aSize Size of data to write
  1.1141 + */
  1.1142 +void SCMDataSave::WriteUart(const TUint8* aData, TInt aSize)
  1.1143 +	{
  1.1144 +	OMAP* assp = ((OMAP*)Arch::TheAsic());
  1.1145 +	TOmapDbgPrt* dbg = assp->DebugPort();
  1.1146 +		
  1.1147 +	if (dbg)
  1.1148 +		{
  1.1149 +		for(TInt i=0;i<aSize;i++)
  1.1150 +			{
  1.1151 +			dbg->DebugOutput(*(aData+i));			
  1.1152 +			}
  1.1153 +		}
  1.1154 +	else
  1.1155 +		{
  1.1156 +		CLTRACE("SCMDataSave::WriteUart ERROR - dbg was null");		
  1.1157 +		}
  1.1158 +	}
  1.1159 +
  1.1160 +/**
  1.1161 + * Setter for the current number of bytes written for this crash log
  1.1162 + * If aByte is not word aligned, it will be rounded up to be so
  1.1163 + * @param aByte Current bytes written
  1.1164 + */
  1.1165 +void SCMDataSave::SetByteCount(TInt aByte)
  1.1166 +	{
  1.1167 +	//ensure aligned
  1.1168 +	if(aByte % iWriter->GetCacheSize() == 0)
  1.1169 +		{
  1.1170 +		iByteCount = aByte;
  1.1171 +		}
  1.1172 +	else
  1.1173 +		{
  1.1174 +		iByteCount = aByte + (iWriter->GetCacheSize() - (aByte % iWriter->GetCacheSize()));
  1.1175 +		}		
  1.1176 +	}
  1.1177 +
  1.1178 +/**
  1.1179 + * Gets the output target selection
  1.1180 + * @return TScmWriteSelect output target selection
  1.1181 + * @param void
  1.1182 + */	
  1.1183 +SCMDataSave::TWriteSelect SCMDataSave::GetWriteSelect()
  1.1184 +	{
  1.1185 +	return iWriteSelect;
  1.1186 +	}
  1.1187 +
  1.1188 +/**
  1.1189 + * Sets the output target selection
  1.1190 + * @return void
  1.1191 + * @param TScmWriteSelect aWriteSelect output target selection
  1.1192 + */
  1.1193 +void SCMDataSave::SetWriteSelect(SCMDataSave::TWriteSelect aWriteSelect)
  1.1194 +	{
  1.1195 +	iWriteSelect = aWriteSelect;
  1.1196 +	}
  1.1197 +
  1.1198 +/**
  1.1199 + * Gets the amount of space remaining for the media of choice
  1.1200 + * @return
  1.1201 + */
  1.1202 +TUint SCMDataSave::SpaceRemaining()
  1.1203 +	{
  1.1204 +	TInt currentPosition = iWriter->GetBytesWritten() + iStartingPointForCrash;
  1.1205 +	
  1.1206 +	return MaxLogSize() - currentPosition; 
  1.1207 +	}
  1.1208 +
  1.1209 +/**
  1.1210 + * To find the max size of a log for a given media
  1.1211 + * @return the max size of a log for a given media
  1.1212 + */
  1.1213 +TUint SCMDataSave::MaxLogSize()
  1.1214 +	{
  1.1215 +	//see what write media is being used
  1.1216 +	switch(GetWriteSelect())
  1.1217 +		{
  1.1218 +		case EWriteFlash:
  1.1219 +			{
  1.1220 +			return KMaxCrashLogSize; 
  1.1221 +			}
  1.1222 +		case EWriteComm:
  1.1223 +			{
  1.1224 +			return 0xFFFFFFFF;
  1.1225 +			}
  1.1226 +		default:
  1.1227 +			{
  1.1228 +			return 0;
  1.1229 +			}
  1.1230 +		} 
  1.1231 +	}
  1.1232 +
  1.1233 +/**
  1.1234 + * Records the offset in the flash partition where this crash begins
  1.1235 + * @param aStart Offset in flash
  1.1236 + */
  1.1237 +void SCMDataSave::SetCrashStartingPoint(TUint32 aStart)
  1.1238 +	{
  1.1239 +	iStartingPointForCrash = aStart;
  1.1240 +	}
  1.1241 +
  1.1242 +//eof
  1.1243 +