First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\debug\crashMonitor\src\scmdatasave.cpp
18 #define __INCLUDE_REG_OFFSETS__ // for SP_R13U in nk_plat.h
23 #include <omap_assp.h>
24 #include <scmonitor.h>
25 #include <scmdatasave.h>
29 * @internal technology
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
39 EXPORT_C SCMDataSave::SCMDataSave(Monitor* aMonitor, CrashFlash* aFlash)
43 #ifdef SCM_COMM_OUTPUT
44 ,iWriteSelect(EWriteComm) // write data to debug port
46 ,iWriteSelect(EWriteFlash) // write data to flash
48 ,iPerformChecksum(ETrue) // checksum data
49 ,iStartingPointForCrash(0)
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);
61 SCMDataSave::~SCMDataSave()
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
71 TInt SCMDataSave::GetByteCount()
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
82 TInt SCMDataSave::LogThreadUserStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
89 iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
91 //first we check for a user stack...
92 if (aThread->iUserStackRunAddress && aThread->iUserStackSize)
95 TThreadStack usrStack;
96 usrStack.iStackType = TThreadStack::EUsrStack;
97 usrStack.iThreadId = (TUint64)aThread->iId;
99 //map in the user stack
100 TUint8* usrStart = (TUint8*)iMonitor->MapAndLocateUserStack(aThread); //What about Demand paging??
101 TUint8* usrEnd = (TUint8*)(usrStart + aThread->iUserStackSize);
104 TUint8* stackPointer = (TUint8*)usrSp;
106 //check the stack pointer is in the range of the stack...
107 if (stackPointer < usrStart || stackPointer >= usrEnd)
109 stackPointer = usrStart;
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;
117 aSizeDumped+= usrStack.GetSize();
118 usrStack.Serialize(*iWriter);
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)
126 CLTRACE("Failed to log usr stack");
129 aSizeDumped+= memDumped;
134 aSizeDumped+=usrStack.GetSize();
135 usrStack.Serialize(*iWriter);
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
147 TInt SCMDataSave::LogThreadSupervisorStack(DThread* aThread, TBool aFullStack, TUint& aSizeDumped)
154 iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
156 //now we dump the supervisor stack
157 TThreadStack svrStack;
158 svrStack.iStackType = TThreadStack::ESvrStack;
159 svrStack.iThreadId = (TUint64)aThread->iId;
161 if (aThread->iSupervisorStack && aThread->iSupervisorStackSize)
163 TUint8* svrStart = (TUint8*)aThread->iSupervisorStack;
164 TUint8* svrEnd = (TUint8*)(svrStart + aThread->iSupervisorStackSize);
165 TUint8* svrStackPointer = (TUint8*)svSp;
167 //size of stack we are to dump
168 svrStack.iStackSize = aFullStack || (svrStackPointer == svrStart) ? svrEnd - svrStart : svrEnd - svrStackPointer;
172 //check the stack pointer is in the range of the stack...
173 if (svrStackPointer < svrStart || svrStackPointer >= svrEnd)
175 svrStackPointer = svrStart;
178 //write struct to flash
179 aSizeDumped+=svrStack.GetSize();
180 svrStack.Serialize(*iWriter);
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;
187 if(KErrNone != memErr)
189 CLTRACE("Failed to log supervisor stack");
195 aSizeDumped+=svrStack.GetSize();
196 svrStack.Serialize(*iWriter);
204 * Takes a DProcess kernel object and logs its corrosponding code segments
206 * @param aSizeDumped Holds the size of the data dumped
207 * @return one of the OS wide error codes
209 TInt SCMDataSave::LogCodeSegments(DProcess* aProc, TUint& aSizeDumped)
214 //the code segment set for this process
215 TCodeSegmentSet segSet;
216 segSet.iPid = (TUint64)aProc->iId;
218 //make sure list mutex is ok
219 if(Kern::CodeSegLock()->iHoldCount)
226 aProc->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
228 //iterate through the list
230 for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
233 DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
246 segSet.iNumSegs = codeSegCnt;
247 segSet.Serialize(*iWriter);
248 aSizeDumped+=segSet.GetSize();
250 TModuleMemoryInfo memoryInfo;
252 //now we write each code segment
253 for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
256 DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
261 seg.iXip = (codeSeg->iXIP) ? ETrue : EFalse;
263 //Get the code seg type
266 seg.iCodeSegType = EExeCodeSegType;
268 else if(codeSeg->IsDll())
270 seg.iCodeSegType = EDllCodeSegType;
273 TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
276 seg.iCodeSegMemInfo = memoryInfo;
280 seg.iCodeSegMemInfo.iCodeSize = 0;
282 // Still need to indicate it wasnt available somehow
286 seg.iNameLength = codeSeg->iFileName->Length();
287 seg.iName = *(codeSeg->iFileName);
289 aSizeDumped+=seg.GetSize();
290 seg.Serialize(*iWriter);
294 //Empty this queue and clear marks
295 DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
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
305 TInt SCMDataSave::LogRomInfo(TUint& aSizeDumped)
309 TRomHeaderData romData;
311 TRomHeader rHdr = Epoc::RomHeader();
313 romData.iMajorVersion = rHdr.iVersion.iMajor;
314 romData.iMinorVersion = rHdr.iVersion.iMinor;
315 romData.iBuildNumber = rHdr.iVersion.iBuild;
316 romData.iTime = rHdr.iTime;
318 TInt err = romData.Serialize(*iWriter);
324 aSizeDumped += romData.GetSize();
330 * Takes a DProcess kernel object and logs to flash
332 * @param aSizeDumped Holds the size of the data dumped
333 * @return one of the OS wide error codes
335 TInt SCMDataSave::LogProcessData(DProcess* aProc, TUint& aSizeDumped)
340 TProcessData procData;
341 DCodeSeg* codeSeg = aProc->iCodeSeg;
343 procData.iPriority = aProc->iPriority;
344 procData.iPid = (TUint64)aProc->iId;
346 //the code segment is not always available
349 procData.iNamesize = codeSeg->iFileName->Length();
350 procData.iName = *(codeSeg->iFileName);
353 aSizeDumped += procData.GetSize();
354 procData.Serialize(*iWriter);
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
367 TInt SCMDataSave::LogCrashHeader(const TDesC8& aCategory, TInt aReason, TInt aCrashId, TUint& aSizeDumped)
372 //the thread that crashed is the context in which we are running
373 DThread* crashedThread = &Kern::CurrentThread();
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();
383 iCrashInf.iCategorySize = aCategory.Length();
384 iCrashInf.iCategory = aCategory;
385 iCrashInf.iCrashId = aCrashId;
387 iCrashInf.iFlashBlockSize = KCrashLogBlockSize;;
388 iCrashInf.iFlashPartitionSize = KCrashLogSize;;
390 TSuperPage& sp=Kern::SuperPage();
391 iCrashInf.iExcCode = sp.iKernelExcId;
393 //These will be updated with more info at end of crash
394 aSizeDumped+=iCrashInf.GetSize();
395 iCrashInf.Serialize(*iWriter);
397 aSizeDumped+=iHdr.GetSize();
398 iHdr.Serialize(*iWriter);
400 CLTRACE1("(SCMDataSave::LogCrashHeader) finished bytes written= %d", iWriter->GetBytesWritten());
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
410 TInt SCMDataSave::LogThreadData(DThread* aThread, TUint& aSizeDumped)
415 //struct to hold data that gets written to flash
416 TThreadData threadData;
418 threadData.iTid = (TUint64)aThread->iId;
419 threadData.iOwnerId = (TUint64)aThread->iOwningProcess->iId;
420 threadData.iPriority = aThread->iThreadPriority;
422 //Get the stack pointers
424 iMonitor->GetStackPointers(&(aThread->iNThread), svSp, usrSp );
425 threadData.iUsrSP = usrSp;
426 threadData.iSvcSP = svSp;
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;
434 //currently we can only get the kernels heap
435 if(aThread == &Kern::CurrentThread())
439 TInt err = FindKernelHeap(heapLoc,heapSz);
442 threadData.iSvcHeap = heapLoc;
443 threadData.iSvcHeapSize = heapSz;
447 CLTRACE("\tError: Unable to get kernel heap");
453 aThread->TraceAppendFullName(filename, EFalse);
455 threadData.iName.Copy(filename);
456 threadData.iNamesize = threadData.iName.Length();
459 #ifdef __INCLUDE_NTHREADBASE_DEFINES__
460 threadData.iLastCpu = aThread->iNThread.iLastCpu;
462 threadData.iLastCpu = aThread->iNThread.iSpare3;
465 threadData.Serialize(*iWriter);
466 aSizeDumped+=threadData.GetSize();
472 * Logs the arm exception stacks
473 * @param aSizeDumped Holds the size of the data dumped
474 * @return one of the OS wide codes
476 TInt SCMDataSave::LogExceptionStacks(TUint& aSizeDumped)
482 #if defined(__EPOC32__) && !defined(__CPU_X86)
484 TStackInfo& stackInfo = Kern::SuperPage().iStackInfo;
486 TThreadStack irqStack;
487 irqStack.iStackType = TThreadStack::EIRQStack;
488 irqStack.iStackSize = stackInfo.iIrqStackSize;
490 aSizeDumped+=irqStack.GetSize();
491 irqStack.Serialize(*iWriter);
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));
496 if(KErrNone != irqErr)
498 CLTRACE("*****Failed to log IRQ stack");
500 aSizeDumped+=memDumped;
502 //Next, we do the FIQ stack
503 TThreadStack fiqStack;
504 fiqStack.iStackType = TThreadStack::EFIQStack;
505 fiqStack.iStackSize = stackInfo.iFiqStackSize;
507 aSizeDumped+=fiqStack.GetSize();
508 fiqStack.Serialize(*iWriter);
510 //Now dump the stack itself
511 MTRAPD(fiqErr, LogMemory((TUint8*)stackInfo.iFiqStackBase, stackInfo.iFiqStackSize, &Kern::CurrentThread(), memDumped));
513 if(KErrNone != fiqErr )
515 CLTRACE("*****Failed to log FIQ stack");
517 aSizeDumped+=memDumped;
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
529 TInt SCMDataSave::LogCPURegisters(TUint& aSizeDumped)
536 //meta data about the thread set
537 TRegisterSet threadSet;
538 threadSet.iNumRegisters = fullSet;
540 aSizeDumped+=threadSet.GetSize();
541 threadSet.Serialize(*iWriter);
543 SFullArmRegSet regSet;
544 ReadCPURegisters(regSet);
545 TArmReg* regs = (TArmReg*)®Set;
548 for(cnt = 0; cnt < fullSet; cnt++)
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;
556 aSizeDumped+=regVal.GetSize();
557 regVal.Serialize(*iWriter);
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
570 TInt SCMDataSave::LogRegisters(DThread* aThread, const TRegisterSetType& aRegType, TUint& aSizeDumped)
576 TUint32 availableRegs;
579 //for the current thread we do things differently
580 if(aThread == &Kern::CurrentThread() && aRegType == EFullCPURegisters)
582 err = LogCPURegisters(aSizeDumped);
585 else if(aThread == &Kern::CurrentThread())
587 //only do full cpu reg for the current thread
588 return KErrNotSupported;
591 //Read the appropriate registers
594 case EUserRegisters :
596 err = ReadUserRegisters(aThread, regs, availableRegs);
599 case ESupervisorRegisters :
601 err = ReadSystemRegisters(aThread, regs, availableRegs);
604 default : return KErrNotSupported;
612 //meta data about the thread set
613 TRegisterSet threadSet;
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
617 for(TInt cnt =0; cnt< 8*sizeof(availableRegs); cnt++) //cycle through 1 bit at a time
619 if(0x1 & (availableRegs>>cnt))
623 threadSet.iNumRegisters = numR;
628 threadSet.Serialize(*iWriter);
629 aSizeDumped += threadSet.GetSize();
631 TInt32 currentRegister = 1;
632 TArmReg* reg = (TArmReg*)(®s);
634 for(TInt32 cnt = 0; cnt < KArmRegisterCount; cnt++)
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)
640 //this is the struct to store the register value in
641 TRegisterValue regVal;
643 //get register type as per symbian elf docs
644 TUint32 registerType;
645 err = GetRegisterType(aRegType, cnt, registerType);
650 regVal.iType = registerType;
651 regVal.iOwnId = aThread->iId;
654 regVal.iValue32 = reg[cnt];
656 aSizeDumped+=regVal.GetSize();
657 regVal.Serialize(*iWriter);
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
674 TInt SCMDataSave::LogMemory(const TUint8* aStartAddress, TInt aLength, const DThread* aThread, TUint& aSizeDumped)
679 if(aThread->iOwningProcess != &Kern::CurrentProcess())
681 TInt err = iMonitor->SwitchAddressSpace(aThread->iOwningProcess, ETrue);
689 memDump.iStartAddress = (TUint32)aStartAddress;
690 memDump.iLength = aLength;
691 memDump.iPid = aThread->iOwningProcess->iId;
693 aSizeDumped+=memDump.GetSize();
694 memDump.Serialize(*iWriter);
702 theMemory.iData.Set(const_cast<TUint8*>(aStartAddress), aLength, aLength);
704 theMemory.Serialize(*iWriter);
705 aSizeDumped+=theMemory.GetSize();
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
715 TInt SCMDataSave::LogLocks(TUint& aSizeDumped)
720 // get the mutex logs & waits & log via a TLockData object
721 TSCMLockData lockData;
723 const TInt KMaxLockCheck = 20; // so no possibility of infinite loop
726 // check for kernel locks -
727 for(TInt i=0;i<KMaxLockCheck;i++)
729 TBool locked = NKern::KernelLocked(i);
732 lockData.SetLockCount(lockCount);
735 // found a valid lock for value i increment the clock counter
740 DMutex* mutex = Kern::CodeSegLock();
743 lockData.SetMutexHoldCount(mutex->iHoldCount);
744 lockData.SetMutexThreadWaitCount(mutex->iWaitCount);
748 // no mutex held set to -1
749 lockData.SetMutexHoldCount(0);
750 lockData.SetMutexThreadWaitCount(0);
753 aSizeDumped+=lockData.GetSize();
754 TInt err = lockData.Serialize(*iWriter);
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
764 TInt SCMDataSave::LogConfig(SCMConfiguration& aScmConfig)
766 iWriter->SetPosition(0);
768 TInt err = aScmConfig.Serialize(*iWriter);
772 CLTRACE1("SCMDataSave::LogConfig failed err = %d", err);
779 * Reads the SCM Configuration from the media
781 * @return one of the system wide codes
783 TInt SCMDataSave::ReadConfig(SCMConfiguration& aScmConfig)
785 const TInt KBufSize = 135; //Not yet done: Put in header, beside config defn
787 if( KBufSize < aScmConfig.GetSize())
789 CLTRACE2("(SCMDataSave::ReadConfig) ** ERROR Inadequate buffer actual = %d req = %d"
790 , KBufSize, aScmConfig.GetSize());
793 // try and read the configuration
795 buf.SetLength(KBufSize);
797 iFlash->SetReadPos(0); // config always at 0
800 TByteStreamReader reader(const_cast<TUint8*>(buf.Ptr()));
801 TInt err = aScmConfig.Deserialize(reader);
802 if(err == KErrNotReady)
804 CLTRACE("(SCMDataSave::ReadConfig) no config saved - use default");
806 else if(err == KErrNone)
808 CLTRACE("(SCMDataSave::ReadConfig) Config read ok");
812 CLTRACE1("(SCMDataSave::ReadConfig) error reading config err = %d", err);
819 * This is a look up table to map the register type and number to the symbian elf definition
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
826 TInt SCMDataSave::GetRegisterType(const TRegisterSetType& aSetType, TInt32& aRegNumber, TUint32& aRegisterType)
829 if(aRegNumber < EArmR0 || aRegNumber > EArmFlags)
834 //look at what type we are using
837 case EUserRegisters :
839 aRegisterType = aRegNumber * 0x100; //for R0 to R16 (CPSR) it just increments in 0x100 from 0x0 to 0x1000
842 case ESupervisorRegisters :
844 //same as EUserRegisters except R13 and R14 are different
845 if(aRegNumber == EArmSp)
847 aRegisterType = 0x1100;
850 else if(aRegNumber == EArmLr)
852 aRegisterType = 0x1200;
857 aRegisterType = aRegNumber * 0x100;
861 default : return KErrNotSupported;
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
873 TInt SCMDataSave::LogTraceBuffer(TInt aSizeToDump, TUint& aSizeDumped)
879 TBool dumpAll = (aSizeToDump == 0) ? ETrue : EFalse;
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
884 TUint sizeOfPartRead;
885 TInt spaceRemaining = aSizeToDump;
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);
893 TInt err = BTrace::Control(BTrace::ECtrlCrashReadFirst,&data,&sizeOfPartRead);
895 while(KErrNone == err && sizeOfPartRead > 0)
897 TUint rawSize = 0; //how much of this read data want we to dump
901 rawSize = sizeOfPartRead;
903 else //Otherwise see what room is left for dumpage
905 rawSize = ((sizeOfPartRead + iTrace.iSizeOfMemory) > aSizeToDump) ? spaceRemaining : sizeOfPartRead;
908 //Only relevant if restricting the dump
909 if(spaceRemaining <= 0 && !dumpAll)
912 TPtrC8 ptr(data, rawSize);
913 err = LogRawData(ptr, memDumped);
916 CLTRACE1("Logging Raw data failed - [%d]", err);
917 err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
921 aSizeDumped+=memDumped;
923 iTrace.iSizeOfMemory += rawSize;
924 iTrace.iNumberOfParts++;
925 spaceRemaining -= rawSize;
927 err = BTrace::Control(BTrace::ECtrlCrashReadNext,&data,&sizeOfPartRead);
934 * Logs the data in a TRawData struct
936 * @param aSizeDumped Holds the size of the data dumped
937 * @return One of the OS wide codes
939 TInt SCMDataSave::LogRawData(const TDesC8& aData, TUint& aSizeDumped)
942 theData.iLength = aData.Length();
943 theData.iData.Set(const_cast<TUint8*>(aData.Ptr()), aData.Length(), aData.Length());
945 aSizeDumped+=theData.GetSize();
946 return theData.Serialize(*iWriter);
951 * Logs the kernels heap and returns the size dumped via aSizeDumped
952 * @param aSizeDumped Holds the size of the data dumped
955 TInt SCMDataSave::LogKernelHeap(TUint& aSizeDumped)
961 TInt32 err = FindKernelHeap(heapLoc, heapSize);
964 return LogMemory((TUint8*)heapLoc, heapSize, &Kern::CurrentThread(), aSizeDumped);
967 CLTRACE1("\tCouldnt find the kernel heap: [%d]", err);
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
977 TInt SCMDataSave::FindKernelHeap(TInt32& aHeapLocation, TInt32& aHeapSize)
981 //Get Chunk object container
982 DObjectCon* objectContainer = Kern::Containers()[EChunk];
983 if(objectContainer == NULL)
985 CLTRACE("\tFailed to get object container for the chunks");
989 //Must check the mutex on this is ok otherwise the data will be in an inconsistent state
990 if(objectContainer->Lock()->iHoldCount)
992 CLTRACE("\tChunk Container is in an inconsistant state");
996 TInt numObjects = objectContainer->Count();
998 for(TInt cnt = 0; cnt< numObjects; cnt ++)
1000 DChunk* candidateHeapChunk = (DChunk*)(*objectContainer)[cnt];
1002 //Get the objects name
1003 TBuf8<KMaxKernelName> name;
1004 candidateHeapChunk->TraceAppendFullName(name,EFalse);
1006 if(name == KKernelHeapChunkName)
1008 #ifndef __MEMMODEL_FLEXIBLE__
1009 aHeapLocation = (TInt32)candidateHeapChunk->iBase;
1011 aHeapLocation = (TInt32)candidateHeapChunk->iFixedBase;
1014 aHeapSize = candidateHeapChunk->iSize;
1020 return KErrNotFound;
1024 * This logs the variant specific descriptor data to the crash log
1025 * @param aSizeDumped records how much was dumped by this function
1026 * @return one of the OS wide codes
1028 TInt SCMDataSave::LogVariantSpecificData(TUint& aSizeDumped)
1034 //Change this descriptor as required for your needs
1035 _LIT(KVariantSpecificData, "This is the variant specific data. Put your own here");
1037 TVariantSpecificData varData;
1038 varData.iSize = KVariantSpecificData().Size();
1040 TInt err = varData.Serialize(*iWriter);
1043 CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
1046 aSizeDumped+=varData.GetSize();
1048 TUint rawDataSize = 0;
1049 err = LogRawData(KVariantSpecificData(), rawDataSize);
1052 CLTRACE1("\tLogging variant specific data failed with code [%d]", err);
1056 aSizeDumped+=rawDataSize;
1063 * This method is the callback used by MPhysicalWriterImpl interface
1064 * if the TCachedByteStreamWriter is configured to use this interface
1065 * the callback avoids the need for temp buffers & can interface directly with the
1066 * flash writer methods
1067 * @param aData - data to write
1068 * @param aLen - length of data to write
1069 * @param aPos - writers internal position
1071 void SCMDataSave::DoPhysicalWrite(TAny* aData, TInt aPos, TInt aLen)
1073 if(iPerformChecksum)
1075 iChecksum.ChecksumBlock((TUint8*)aData, aLen);
1078 if( this->iWriteSelect == EWriteComm)
1080 WriteUart((TUint8*)aData, aLen);
1089 * Writes data to Flash
1090 * @param aSomething Pointer to the data
1091 * @param aSize Size of the data
1093 void SCMDataSave::Write(const TAny* aSomething, TInt aSize)
1095 TPtrC8 data((const TUint8 *)aSomething, aSize);
1099 WriteCrashFlash(iByteCount, written, data);
1100 iByteCount+= written;
1104 * Writes a descriptor to the crash flash
1105 * @param aPos Position in flash to write
1106 * @param aSize Holds the size of the data written after the call
1107 * @param aBuffer Descriptor to write
1109 void SCMDataSave::WriteCrashFlash(TInt aPos, TInt& aSize, const TDesC8& aBuffer)
1111 //Set write position in the flash
1112 iFlash->SetWritePos(aPos);
1113 iFlash->Write(aBuffer);
1116 aSize += iFlash->BytesWritten();
1118 if(aSize != aBuffer.Length())
1120 CLTRACE2("(SCMDataSave::WriteCrashFlash) Over the limit aSize = %d aBuffer.Length() = %d",
1121 aSize, aBuffer.Length());
1126 * Writes a descriptor via serial
1127 * @param aDes Descriptor to write
1129 void SCMDataSave::WriteUart(const TDesC8& aDes)
1131 WriteUart(aDes.Ptr(), aDes.Length());
1135 * Writes data via serial
1136 * @param aData Data to write
1137 * @param aSize Size of data to write
1139 void SCMDataSave::WriteUart(const TUint8* aData, TInt aSize)
1141 OMAP* assp = ((OMAP*)Arch::TheAsic());
1142 TOmapDbgPrt* dbg = assp->DebugPort();
1146 for(TInt i=0;i<aSize;i++)
1148 dbg->DebugOutput(*(aData+i));
1153 CLTRACE("SCMDataSave::WriteUart ERROR - dbg was null");
1158 * Setter for the current number of bytes written for this crash log
1159 * If aByte is not word aligned, it will be rounded up to be so
1160 * @param aByte Current bytes written
1162 void SCMDataSave::SetByteCount(TInt aByte)
1165 if(aByte % iWriter->GetCacheSize() == 0)
1171 iByteCount = aByte + (iWriter->GetCacheSize() - (aByte % iWriter->GetCacheSize()));
1176 * Gets the output target selection
1177 * @return TScmWriteSelect output target selection
1180 SCMDataSave::TWriteSelect SCMDataSave::GetWriteSelect()
1182 return iWriteSelect;
1186 * Sets the output target selection
1188 * @param TScmWriteSelect aWriteSelect output target selection
1190 void SCMDataSave::SetWriteSelect(SCMDataSave::TWriteSelect aWriteSelect)
1192 iWriteSelect = aWriteSelect;
1196 * Gets the amount of space remaining for the media of choice
1199 TUint SCMDataSave::SpaceRemaining()
1201 TInt currentPosition = iWriter->GetBytesWritten() + iStartingPointForCrash;
1203 return MaxLogSize() - currentPosition;
1207 * To find the max size of a log for a given media
1208 * @return the max size of a log for a given media
1210 TUint SCMDataSave::MaxLogSize()
1212 //see what write media is being used
1213 switch(GetWriteSelect())
1217 return KMaxCrashLogSize;
1231 * Records the offset in the flash partition where this crash begins
1232 * @param aStart Offset in flash
1234 void SCMDataSave::SetCrashStartingPoint(TUint32 aStart)
1236 iStartingPointForCrash = aStart;