diff -r 000000000000 -r a41df078684a kerneltest/e32utils/crashread/crashread.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32utils/crashread/crashread.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,346 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include +#include "crashflash.h" +#include +#include + +#ifdef _DEBUG +#define TRACE(a) RDebug::Print(a); PrintLine(a) +#define TRACE1(a,b) RDebug::Print(a,b); PrintLine(a,b) +#define TRACE2(a,b,c) RDebug::Print(a,b,c); PrintLine(a,b,c) +#define TRACE5(a,b,c,d,e,f) RDebug::Print(a,b,c,d,e,f); PrintLine(a,b,c,d,e,f) +#else +#define TRACE(a) +#define TRACE1(a,b) +#define TRACE2(a,b,c) +#define TRACE5(a,b,c,d,e,f) +#endif + +#ifndef _CRASHLOG_COMPR +_LIT(KCrashLogFileName, "?:\\crashlog.txt"); +#else +_LIT(KCrashLogCompFileName, "?:\\crashlog.gz"); +_LIT(KCrashLogCompTruncatedFileName, "?:\\crashlog_truncated.gz"); +#endif //_CRASHLOG_COMPR + +_LIT8(KCrashLogSignatureStomp, "\x00\x00\x00\x00"); + +CConsoleBase* console = 0; + +RLocalDrive gLd; +TLocalDriveCapsV4 gCaps; +TPckg gCapsBuf(gCaps); + +#ifdef _DEBUG +LOCAL_C void CheckConsoleCreated() + { + if(!console) + { + TRAPD(r, console = Console::NewL(_L("crashread"), + TSize(KConsFullScreen,KConsFullScreen))); + __ASSERT_ALWAYS(r == KErrNone, User::Panic(_L("Could not create console"), 1)); + } + } + +LOCAL_C void PrintLine(TRefByValue aFmt,...) + { + // Print to a console screen. + VA_LIST list; + VA_START(list, aFmt); + TBuf<0x100> aBuf; + aBuf.AppendFormatList(aFmt, list); + CheckConsoleCreated(); + console->Write(aBuf); + console->Write(_L("\n\r")); + } +#endif + +/** Read the signature from the flash and verify it is correct. + @return ETrue when signature found, EFalse otherwise +*/ +LOCAL_C TBool SignatureExistsL() + { + TBuf8 buf(0); + User::LeaveIfError(gLd.Read(KCrashLogSizeFieldBytes,KCrashLogSignatureBytes,buf)); + + if(buf.Compare(KCrashLogSignature) == 0) + { + return ETrue; + } + + return EFalse; + } + +LOCAL_C TInt LogSizeL() + { + TBuf8 buf(0); + User::LeaveIfError(gLd.Read(0,KCrashLogSizeFieldBytes,buf)); + TInt size = *((TUint*)(buf.Ptr())); + size -= (KCrashLogHeaderSize); + return size; + } + +#ifdef _CRASHLOG_COMPR +/** Read the log flags from the flash. Flags located after the log size and uncompressed size + @return The log flags byte +*/ +LOCAL_C TUint32 LogFlagsL() + { + TBuf8 buf(0); + User::LeaveIfError(gLd.Read(KCrashLogSizeFieldBytes+KCrashLogUncompSizeFieldBytes+KCrashLogSignatureBytes, + KCrashLogFlagsFieldBytes,buf)); + return *((TUint32*)buf.Ptr()); + } +#endif //_CRASHLOG_COMPR + +LOCAL_C TInt InvalidateSignature() + { + //On Nand we erase the block. + if(gCaps.iType == EMediaNANDFlash) + { + return gLd.Format(0,gCaps.iNumBytesMain * gCaps.iNumPagesPerBlock); + } + //On Nor we just stomp on the first 4 bytes of the signature + return gLd.Write(KCrashLogSizeFieldBytes,KCrashLogSignatureStomp); + } + +/** +@return KErrNone if no read errors, otherwise the last read error. +@leave if other errors occur. +@param aFileName Where the log wll be copied to +@param aStartPosition Where to begin reads within the flash section. +@param aLogSize The total amount to read. +*/ +TInt CopyToFileL(const TDesC& aFileName, const TInt aStartPosition, const TInt aLogSize) + { + // Connect to f32 and write out the file + RFs fs; + RFile file; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + User::LeaveIfError(file.Replace(fs, aFileName, EFileWrite)); + CleanupClosePushL(file); + + //create buffer + const TInt KBufferSize=32*1024; + HBufC8* buf = HBufC8::NewLC(KBufferSize); + TPtr8 ptr = buf->Des(); + + TInt readError = KErrNone; + for(TInt offset=0; offset crashLogFileName(KCrashLogFileName); + crashLogFileName[0] = systemDriveChar; + r = CopyToFileL(crashLogFileName, KCrashLogSizeFieldBytes+KCrashLogSignatureBytes, logSize); + + if (r==KErrNone) + { + TRACE1(_L("Crash log successfully written to: %S."), &crashLogFileName); + } + else + { + TRACE1(_L("Crash log written to %S but errors were encountered when reading, it may be incomplete or corrupt."), &crashLogFileName); + } + +#else + // 2) Read crash log header to get the compressed and uncompressed size of the log + // also need to read the flags to determine if the log had to be truncated and + // if the expected log format is found + const TUint32 logFlags = LogFlagsL(); + + // Extract byte offset from the end of the header to the start of the log data + const TInt logOff = logFlags>>KCrashLogFlagOffShift; + + // Work out if the log had to be truncated + const TInt truncated = logFlags&KCrashLogFlagTruncated; + + // Check the crashlog type flag is that expected - here we can only cope with GZIP compatible logs + if ((logFlags & (0xffffffff>>(32-KCrashLogFlagTypeBits))) != KCrashLogFlagGzip) + {// wrong log type so can't extract it + TRACE(_L("Crash Log data is stored in an incompatible data format so can't be read")); + } + else + { + // 2) Read the log data + const TInt logSize = LogSizeL()-logOff; // don't include any offset bytes + TRACE1(_L("Reading compressed crash log of %d bytes..."), logSize); + + + TRACE1(_L("Writing compressed crash log to file..."), logSize); + RBuf crashLogCompFileName; + if (!truncated) + { + crashLogCompFileName.CreateL(KCrashLogCompFileName); + } + else + { + crashLogCompFileName.CreateL(KCrashLogCompTruncatedFileName); + } + crashLogCompFileName.CleanupClosePushL(); + + crashLogCompFileName[0] = systemDriveChar; + r = CopyToFileL(crashLogCompFileName, KCrashLogHeaderSize+logOff, logSize); + + if (r==KErrNone) + { + if (!truncated) + { + TRACE1(_L("Crash log successfully written to: %S."), &crashLogCompFileName); + } + else + { + TRACE(_L("Crash log was truncated, some log data has been lost")); + TRACE1(_L("Crash log successfully written to: %S."), &crashLogCompFileName); + } + } + else + { + if(!truncated) + { + TRACE1(_L("Crash log written to %S but errors were encountered when reading, it may be incomplete or corrupt."), &crashLogCompFileName); + } + else + { + TRACE1(_L("Crash log written to %S but errors were encountered when reading, it may be incomplete or corrupt."), &crashLogCompFileName); + } + } + CleanupStack::PopAndDestroy(&crashLogCompFileName); + } +#endif //_CRASHLOG_COMPR + } + + // 5) Stomp on the signature to mark it eligible to be overwritten + TRACE(_L("Overwriting existing signature to indicate crash log has been read...")); + User::LeaveIfError(InvalidateSignature()); + + CleanupStack::PopAndDestroy(&gLd); + + if (r==KErrNone) + { + TRACE(_L("Crash reader finished successfully.")); + } + else + { + TRACE(_L("Crash reader finished but with errors.")); + } + return KErrNone; + } + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + CTrapCleanup* cleanup=CTrapCleanup::New(); + TRAPD(ret, MainL()); + if(console) + { + console->Getch(); + delete console; + } + if (ret){} // stops compile warning + delete cleanup; + __UHEAP_MARKEND; + return KErrNone; + }