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) 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:
// Partition Management for Embedded MMC devices
//
//
#include <drivers/emmcptn.h>
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "locmedia_ost.h"
#ifdef __VC32__
#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
#endif
#include "emmcptnTraces.h"
#endif
const TInt KDiskSectorShift=9;
class DLegacyEMMCPartitionInfo : public DEMMCPartitionInfo
{
public:
DLegacyEMMCPartitionInfo();
~DLegacyEMMCPartitionInfo();
public:
virtual TInt Initialise(DMediaDriver* aDriver);
virtual TInt PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack);
virtual TInt PartitionCaps(TLocDrv& aDrive, TDes8& aInfo);
protected:
void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
private:
static void SessionEndCallBack(TAny* aSelf);
void DoSessionEndCallBack();
virtual TInt DecodePartitionInfo();
protected:
DMediaDriver* iDriver;
TPartitionInfo* iPartitionInfo;
TMMCCallBack iSessionEndCallBack;
TMMCCallBack iCallBack; // Where to report the PartitionInfo completion
DMMCSession* iSession;
TMMCard* iCard;
TUint8* iIntBuf;
};
DLegacyEMMCPartitionInfo::DLegacyEMMCPartitionInfo()
: iSessionEndCallBack(DLegacyEMMCPartitionInfo::SessionEndCallBack, this)
{
OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DLEGACYEMMCPARTITIONINFO_ENTRY );
}
DLegacyEMMCPartitionInfo::~DLegacyEMMCPartitionInfo()
{
OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_ENTRY );
delete iSession;
OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_EXIT );
}
TInt DLegacyEMMCPartitionInfo::Initialise(DMediaDriver* aDriver)
{
OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_INITIALISE_ENTRY, this );
iDriver = aDriver;
DMMCSocket* socket = ((DMMCSocket*)((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSocket);
if(socket == NULL)
{
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT1, this, KErrNoMemory );
return KErrNoMemory;
}
DMMCStack* stack = socket->Stack(0);
iCard = stack->CardP(((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSlotNumber);
iSession = stack->AllocSession(iSessionEndCallBack);
if (iSession == NULL)
return KErrNoMemory;
iSession->SetStack(stack);
iSession->SetCard(iCard);
// this gets used before any access
TInt bufLen, minorBufLen;
stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT2, this, KErrNone );
return KErrNone;
}
TInt DLegacyEMMCPartitionInfo::PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack)
{
OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_ENTRY, this );
iPartitionInfo = &anInfo;
iCallBack = aCallBack;
// If media driver is persistent (see EMediaDriverPersistent),
// the card may have changed since last power down, so reset CID
iSession->SetCard(iCard);
iSession->SetupCIMReadBlock(0, iIntBuf);
TInt r = iDriver->InCritical();
if (r == KErrNone)
r = iSession->Engage();
if(r != KErrNone)
iDriver->EndInCritical();
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_EXIT, this, r );
return r;
}
TInt DLegacyEMMCPartitionInfo::PartitionCaps(TLocDrv& aDrive, TDes8& aInfo)
{
OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_ENTRY, this );
TLocalDriveCapsV6Buf& Info = static_cast< TLocalDriveCapsV6Buf&> (aInfo);
// is this query for the swap partition ?
if (aDrive.iPartitionType == KPartitionTypePagedData)
{
Info().iFileSystemId = KDriveFileNone;
Info().iDriveAtt|= KDriveAttHidden;
}
// is this query for the ROFS partition ?
if (aDrive.iPartitionType == KPartitionTypeRofs)
{
Info().iFileSystemId = KDriveFileSysROFS;
Info().iMediaAtt&= ~KMediaAttFormattable;
Info().iMediaAtt|= KMediaAttWriteProtected;
}
// is this query for the ROM partition ?
if (aDrive.iPartitionType == KPartitionTypeROM)
{
Info().iFileSystemId = KDriveFileNone;
Info().iMediaAtt&= ~KMediaAttFormattable;
Info().iMediaAtt|= KMediaAttWriteProtected;
}
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_EXIT, this, KErrNone );
return KErrNone;
}
void DLegacyEMMCPartitionInfo::SessionEndCallBack(TAny* aSelf)
{
OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_ENTRY );
DLegacyEMMCPartitionInfo& self = *static_cast<DLegacyEMMCPartitionInfo*>(aSelf);
self.DoSessionEndCallBack();
OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_EXIT );
}
void DLegacyEMMCPartitionInfo::DoSessionEndCallBack()
{
OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_ENTRY, this );
iDriver->EndInCritical();
TInt r = iSession->EpocErrorCode();
if (r == KErrNone)
r = DecodePartitionInfo();
iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_EXIT, this );
}
TInt DLegacyEMMCPartitionInfo::DecodePartitionInfo()
//
// decode partition info that was read into internal buffer
//
{
OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ENTRY, this );
TUint partitionCount=iPartitionInfo->iPartitionCount=0;
TInt defaultPartitionNumber=-1;
TMBRPartitionEntry* pe;
const TUint KMBRFirstPartitionOffsetAligned = KMBRFirstPartitionOffset & ~3;
TInt i;
// Read of the first sector successful so check for a Master Boot Record
if (*(TUint16*)(&iIntBuf[KMBRSignatureOffset])!=0xAA55)
{
// If no valid signature give up now, No way to re-format an internal drive correctly
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT1, this, KErrCorrupt );
return KErrCorrupt;
}
__ASSERT_COMPILE(KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry) <= KMBRSignatureOffset);
memmove(&iIntBuf[0], &iIntBuf[2],
KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry));
for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
{
if (pe->IsDefaultBootPartition())
{
SetPartitionEntry(&iPartitionInfo->iEntry[0],pe->iFirstSector,pe->iNumSectors);
defaultPartitionNumber=i;
partitionCount++;
break;
}
}
// Now add any other partitions
for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
{
if (defaultPartitionNumber==i)
{
// Already sorted
}
// FAT partition ?
else if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition() || pe->IsValidExFATPartition())
{
SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
__KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: FAT partition found at sector #%u", pe->iFirstSector));
OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_FAT, "FAT partition found at sector #%x", pe->iFirstSector);
partitionCount++;
}
else if (pe->iPartitionType == KPartitionTypeROM)
{
TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
partitionEntry.iPartitionType = pe->iPartitionType;
partitionCount++;
__KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeROM found at sector #%u", pe->iFirstSector));
OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROM, "KPartitionTypeROM found at sector #%x", pe->iFirstSector);
}
// ROFS partition ?
else if (pe->iPartitionType == KPartitionTypeRofs)
{
// Don't expose this for normal operation only boot?
TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
partitionEntry.iPartitionType = pe->iPartitionType;
__KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeRofs found at sector #%u", pe->iFirstSector));
OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROFS, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
partitionCount++;
}
// Swap partition ?
else if (pe->iPartitionType == KPartitionTypePagedData)
{
__KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypePagedData found at sector #%u", pe->iFirstSector));
OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_PAGED, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
partitionEntry.iPartitionType = pe->iPartitionType;
partitionCount++;
}
}
// Check the validity of the partition address boundaries
// If there is any MBR errors
if(partitionCount > 0)
{
const TInt64 deviceSize = iCard->DeviceSize64();
TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1];
// Check that the card address space boundary is not exceeded by the last partition
if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize)
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space"));
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT2, this, KErrCorrupt );
return KErrCorrupt;
}
// More than one partition. Go through all of them
if (partitionCount > 0)
{
for(i=partitionCount-1; i>0; i--)
{
const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
// Check if partitions overlap
if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions"));
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT3, this, KErrCorrupt );
return KErrCorrupt;
}
}
}
}
if (defaultPartitionNumber==(-1) && partitionCount==0)
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("No Valid Partitions Found!"));
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT4, this, KErrCorrupt );
return KErrCorrupt;
}
iPartitionInfo->iPartitionCount=partitionCount;
iPartitionInfo->iMediaSizeInBytes=iCard->DeviceSize64();
#ifdef _DEBUG
__KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)",partitionCount));
for (TUint x=0; x<partitionCount; x++)
__KTRACE_OPT(KPBUSDRV, Kern::Printf(" Partition%d (B:%xH L:%xH)",x,I64LOW(iPartitionInfo->iEntry[x].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[x].iPartitionLen)));
#endif
//Notify medmmc that partitioninfo is complete.
iCallBack.CallBack();
OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT5, this, KErrNone );
return KErrNone;
}
void DLegacyEMMCPartitionInfo::SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors)
//
// auxiliary static function to record partition information in TPartitionEntry object
//
{
OstTraceFunctionEntryExt( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_ENTRY, this );
aEntry->iPartitionBaseAddr=aFirstSector;
aEntry->iPartitionBaseAddr<<=KDiskSectorShift;
aEntry->iPartitionLen=aNumSectors;
aEntry->iPartitionLen<<=KDiskSectorShift;
aEntry->iPartitionType=KPartitionTypeFAT12;
OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_EXIT, this );
}
// End - DLegacyEMMCPartitionInfo
EXPORT_C DEMMCPartitionInfo* CreateEmmcPartitionInfo()
{
OstTraceFunctionEntry0( _CREATEEMMCPARTITIONINFO_ENTRY );
return new DLegacyEMMCPartitionInfo;
}
DECLARE_STANDARD_EXTENSION()
{
return KErrNone;
}