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