Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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:
// Tests erasing of Flash. Does not test suspending (see TF_SUSPEND)
//
//
#include <e32std.h>
#include <e32std_private.h>
#include <e32svr.h>
#include <e32test.h>
#include "randgen.h"
#include "user_config.h"
RTest test( _L("TF_ERASE") );
class CEraseTest : public CBase
{
public:
~CEraseTest();
void CreateL();
void DoTest();
private:
void DoSimpleTest();
void DoSimpleTest2();
void DoPseudoRandomTest();
void DoRangeTest();
TInt EraseOneBlock( TInt aBlockNumber );
TInt ZeroFillBlock( TInt aBlockNumber );
TBool ValidateBlock( TInt aBlockNumber, TUint32 aFillWord );
private:
TBusLocalDrive iDrive;
TBool iDriveOpened;
TInt iFlashSize;
TInt iBlockSize;
TInt iBlockCount;
TBuf8<512> iReadBuffer;
};
CEraseTest::~CEraseTest()
{
if( iDriveOpened )
{
iDrive.Disconnect();
}
}
void CEraseTest::CreateL()
{
//
// Load the device drivers
//
#ifndef SKIP_PDD_LOAD
test.Printf( _L("Loading %S\n"), &KLfsDriverName );
r = User::LoadPhysicalDevice( KLfsDriverName );
test( KErrNone == r || KErrAlreadyExists == r );
#endif
#ifdef UNMOUNT_DRIVE
RFs fs;
test( KErrNone == fs.Connect() );
#if 0
// XXX - not eka2
test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) );
#endif
TFullName name;
fs.FileSystemName( name, KLffsLogicalDriveNumber );
if( name.Length() > 0 )
{
test.Printf( _L("Unmounting drive") );
test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) );
User::After( 2000000 );
test.Printf( _L("Drive unmounted") );
}
fs.Close();
#endif
//
// Open a TBusLogicalDevice to drive
//
test.Printf( _L("Opening media channel\n") );
static TBool changedFlag = EFalse;
User::LeaveIfError( iDrive.Connect( KDriveNumber, changedFlag ) );
iDriveOpened = ETrue;
//
// Get size of Flash drive, block size, block count
//
TLocalDriveCapsV2Buf info;
iDrive.Caps(info);
iFlashSize = I64LOW(info().iSize);
iBlockSize = info().iEraseBlockSize;
iBlockCount = iFlashSize / iBlockSize;
test.Printf( _L("Flash size is 0x%x bytes\n"), iFlashSize );
test.Printf( _L("Block size is 0x%x bytes\n"), iBlockSize );
test.Printf( _L("Block count is %d\n"), iBlockCount );
test.Printf( _L("CreateL complete\n") );
}
void CEraseTest::DoTest()
//
// Main test dispatcher
//
{
test.Next( _L("Starting tests...") );
DoSimpleTest();
DoSimpleTest2();
DoPseudoRandomTest();
DoRangeTest();
}
TInt CEraseTest::EraseOneBlock( TInt aBlockNumber )
//
// Erases block aBlockNumber on Flash
//
{
TInt blockBaseOffset = aBlockNumber * iBlockSize;
test.Printf( _L("Erasing block %d (offs=0x%x)\n"), aBlockNumber, blockBaseOffset );
TInt r = iDrive.Format( blockBaseOffset, iBlockSize );
test.Printf( _L("... Format returned %d\n"), r );
return r;
}
TBool CEraseTest::ValidateBlock( TInt aBlockNumber, TUint32 aFillWord )
//
// Checks that every word in block aBlockNumber has the value aFillWord
//
{
TUint offset = aBlockNumber * iBlockSize;
test.Printf( _L("Validating block %d (offs=0x%x)\n"), aBlockNumber, offset );
TBool failed = EFalse;
const TInt readBufLen = iReadBuffer.MaxLength();
for( TInt len = iBlockSize; len > 0 && !failed ;)
{
TInt r = iDrive.Read( offset, readBufLen, iReadBuffer );
if( r != KErrNone )
{
test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset );
test( KErrNone == r );
}
test( iReadBuffer.Length() == readBufLen );
TUint32* p = (TUint32*)iReadBuffer.Ptr();
for( TInt i = 0; i < readBufLen; i += 4 )
{
if( aFillWord != *p )
{
failed = ETrue;
test.Printf( _L("... FAILED: word @ offs=0x%x, read=0x%x, expected=0x%x\n"),
offset+i, p[0], aFillWord );
break;
}
++p;
}
offset += readBufLen;
len -= readBufLen;
}
return !failed;
}
TInt CEraseTest::ZeroFillBlock( TInt aBlockNumber )
//
// Zero-fills an entire block
// The requires that writing works (so as a side-effect performs a
// very basic test of writing)
//
{
test.Printf( _L("Zero-filling block %d\n"), aBlockNumber );
//
// Create a buffer full of zeros
//
const TInt KZeroBufSize = 512;
TBuf8<KZeroBufSize> buf;
buf.FillZ( buf.MaxLength() );
//
// Write the data out to the Flash
//
TInt writeCount = iBlockSize / KZeroBufSize;
TInt r = KErrNone;
TInt blockBaseOffset = aBlockNumber * iBlockSize;
for( ; (writeCount > 0) && (KErrNone == r); writeCount-- )
{
r = iDrive.Write( blockBaseOffset, buf );
if( r != KErrNone )
{
test.Printf( _L("... FAIL: write failed (%d) at offset 0x%x\n"), r, blockBaseOffset );
}
blockBaseOffset += KZeroBufSize;
}
return r;
}
void CEraseTest::DoSimpleTest()
//
// Simple erase test. This just zero-fills and then erases each block in turn
//
{
test.Next( _L("Simple test: erases each block in turn\n") );
for( TInt block = 0; block < iBlockCount; block++ )
{
test( KErrNone == ZeroFillBlock( block ) );
test( ValidateBlock( block, 0 ) );
test( KErrNone == EraseOneBlock( block ) );
test( ValidateBlock( block, 0xFFFFFFFF ) );
}
}
void CEraseTest::DoSimpleTest2()
//
// Another simple erase test.
// This time we zero-fill all blocks first, then erase them all
//
{
test.Next( _L("Simple test2 : zero-fills whole Flash, then erases all blocks\n") );
for( TInt block = 0; block < iBlockCount; block++ )
{
test( KErrNone == ZeroFillBlock( block ) );
test( ValidateBlock( block, 0 ) );
}
for( TInt block = 0; block < iBlockCount; block++ )
{
test( KErrNone == EraseOneBlock( block ) );
test( ValidateBlock( block, 0xFFFFFFFF ) );
}
}
void CEraseTest::DoPseudoRandomTest()
//
// Erases the blocks in pseudo-random order, zero-filling first
//
{
test.Next( _L("Test random erase order\n") );
TRandomGenerator random;
#if 0
random.SetSeed( TInt64(0x1020466E, 0x3F9C0C00) );
#else
random.SetSeed( 0x1020466E );
#endif
for( TInt count = 0; count < 50; count++ )
{
TUint block = random.Next() % iBlockCount;
test( KErrNone == ZeroFillBlock( block ) );
test( ValidateBlock( block, 0 ) );
test( KErrNone == EraseOneBlock( block ) );
test( ValidateBlock( block, 0xFFFFFFFF ) );
}
}
void CEraseTest::DoRangeTest()
//
// Simple erase test. This just zero-fills and then erases each block in turn
//
{
test.Next( _L("Range test: check that erase only affects erased block\n") );
//
// Pre-fill all blocks with zero
//
test.Printf( _L("Pre-zeroing blocks\n") );
for( TInt block = 0; block < iBlockCount; block++ )
{
test( KErrNone == ZeroFillBlock( block ) );
test( ValidateBlock( block, 0 ) );
}
//
// The test is to erase a block. Check it is erased and all
// other blocks are still zeros. Then we re-zero the block just
// erased and repeat test with next block
//
test.Printf( _L("Now testing erase...\n") );
for( TInt eraseBlock = 0; eraseBlock < iBlockCount; eraseBlock++ )
{
test( KErrNone == EraseOneBlock( eraseBlock ) );
test( ValidateBlock( eraseBlock, 0xFFFFFFFF ) );
// check all other blocks are still zero
for( TInt j = 0; j < iBlockCount; j++ )
{
if( j != eraseBlock )
{
// test if not the one we just erased
test( ValidateBlock( j, 0 ) );
}
}
// Now zero-fill the block we just erased and move to next block
test( KErrNone == ZeroFillBlock( eraseBlock ) );
test( ValidateBlock( eraseBlock, 0 ) );
}
}
TInt E32Main()
{
test.Title();
test.Start(_L("Testing media erase operations"));
CEraseTest eraseTest;
TRAPD( ret, eraseTest.CreateL() );
if( KErrNone == ret )
{
eraseTest.DoTest();
}
test.End();
return KErrNone;
}