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