1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/medmmc/emmcptn.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,352 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Partition Management for Embedded MMC devices
1.18 +//
1.19 +//
1.20 +
1.21 +#include <drivers/emmcptn.h>
1.22 +#include "OstTraceDefinitions.h"
1.23 +#ifdef OST_TRACE_COMPILER_IN_USE
1.24 +#include "locmedia_ost.h"
1.25 +#ifdef __VC32__
1.26 +#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
1.27 +#endif
1.28 +#include "emmcptnTraces.h"
1.29 +#endif
1.30 +
1.31 +
1.32 +const TInt KDiskSectorShift=9;
1.33 +
1.34 +class DLegacyEMMCPartitionInfo : public DEMMCPartitionInfo
1.35 + {
1.36 +public:
1.37 + DLegacyEMMCPartitionInfo();
1.38 + ~DLegacyEMMCPartitionInfo();
1.39 +public:
1.40 + virtual TInt Initialise(DMediaDriver* aDriver);
1.41 + virtual TInt PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack);
1.42 + virtual TInt PartitionCaps(TLocDrv& aDrive, TDes8& aInfo);
1.43 +
1.44 +protected:
1.45 + void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
1.46 +
1.47 +private:
1.48 + static void SessionEndCallBack(TAny* aSelf);
1.49 + void DoSessionEndCallBack();
1.50 + virtual TInt DecodePartitionInfo();
1.51 +
1.52 +protected:
1.53 + DMediaDriver* iDriver;
1.54 + TPartitionInfo* iPartitionInfo;
1.55 + TMMCCallBack iSessionEndCallBack;
1.56 + TMMCCallBack iCallBack; // Where to report the PartitionInfo completion
1.57 + DMMCSession* iSession;
1.58 + TMMCard* iCard;
1.59 + TUint8* iIntBuf;
1.60 + };
1.61 +
1.62 +DLegacyEMMCPartitionInfo::DLegacyEMMCPartitionInfo()
1.63 + : iSessionEndCallBack(DLegacyEMMCPartitionInfo::SessionEndCallBack, this)
1.64 + {
1.65 + OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DLEGACYEMMCPARTITIONINFO_ENTRY );
1.66 + }
1.67 +
1.68 +DLegacyEMMCPartitionInfo::~DLegacyEMMCPartitionInfo()
1.69 + {
1.70 + OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_ENTRY );
1.71 + delete iSession;
1.72 + OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_EXIT );
1.73 + }
1.74 +
1.75 +TInt DLegacyEMMCPartitionInfo::Initialise(DMediaDriver* aDriver)
1.76 + {
1.77 + OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_INITIALISE_ENTRY, this );
1.78 + iDriver = aDriver;
1.79 +
1.80 + DMMCSocket* socket = ((DMMCSocket*)((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSocket);
1.81 + if(socket == NULL)
1.82 + {
1.83 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT1, this, KErrNoMemory );
1.84 + return KErrNoMemory;
1.85 + }
1.86 +
1.87 + DMMCStack* stack = socket->Stack(0);
1.88 + iCard = stack->CardP(((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSlotNumber);
1.89 +
1.90 + iSession = stack->AllocSession(iSessionEndCallBack);
1.91 + if (iSession == NULL)
1.92 + return KErrNoMemory;
1.93 +
1.94 + iSession->SetStack(stack);
1.95 + iSession->SetCard(iCard);
1.96 +
1.97 + // this gets used before any access
1.98 + TInt bufLen, minorBufLen;
1.99 + stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
1.100 +
1.101 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT2, this, KErrNone );
1.102 + return KErrNone;
1.103 + }
1.104 +
1.105 +TInt DLegacyEMMCPartitionInfo::PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack)
1.106 + {
1.107 + OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_ENTRY, this );
1.108 + iPartitionInfo = &anInfo;
1.109 + iCallBack = aCallBack;
1.110 + // If media driver is persistent (see EMediaDriverPersistent),
1.111 + // the card may have changed since last power down, so reset CID
1.112 + iSession->SetCard(iCard);
1.113 +
1.114 + iSession->SetupCIMReadBlock(0, iIntBuf);
1.115 +
1.116 + TInt r = iDriver->InCritical();
1.117 + if (r == KErrNone)
1.118 + r = iSession->Engage();
1.119 +
1.120 + if(r != KErrNone)
1.121 + iDriver->EndInCritical();
1.122 +
1.123 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_EXIT, this, r );
1.124 + return r;
1.125 + }
1.126 +
1.127 +TInt DLegacyEMMCPartitionInfo::PartitionCaps(TLocDrv& aDrive, TDes8& aInfo)
1.128 + {
1.129 + OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_ENTRY, this );
1.130 + TLocalDriveCapsV6Buf& Info = static_cast< TLocalDriveCapsV6Buf&> (aInfo);
1.131 +
1.132 + // is this query for the swap partition ?
1.133 + if (aDrive.iPartitionType == KPartitionTypePagedData)
1.134 + {
1.135 + Info().iFileSystemId = KDriveFileNone;
1.136 + Info().iDriveAtt|= KDriveAttHidden;
1.137 + }
1.138 +
1.139 + // is this query for the ROFS partition ?
1.140 + if (aDrive.iPartitionType == KPartitionTypeRofs)
1.141 + {
1.142 + Info().iFileSystemId = KDriveFileSysROFS;
1.143 + Info().iMediaAtt&= ~KMediaAttFormattable;
1.144 + Info().iMediaAtt|= KMediaAttWriteProtected;
1.145 + }
1.146 +
1.147 + // is this query for the ROM partition ?
1.148 + if (aDrive.iPartitionType == KPartitionTypeROM)
1.149 + {
1.150 + Info().iFileSystemId = KDriveFileNone;
1.151 + Info().iMediaAtt&= ~KMediaAttFormattable;
1.152 + Info().iMediaAtt|= KMediaAttWriteProtected;
1.153 + }
1.154 +
1.155 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_EXIT, this, KErrNone );
1.156 + return KErrNone;
1.157 + }
1.158 +
1.159 +void DLegacyEMMCPartitionInfo::SessionEndCallBack(TAny* aSelf)
1.160 + {
1.161 + OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_ENTRY );
1.162 + DLegacyEMMCPartitionInfo& self = *static_cast<DLegacyEMMCPartitionInfo*>(aSelf);
1.163 + self.DoSessionEndCallBack();
1.164 + OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_EXIT );
1.165 + }
1.166 +
1.167 +void DLegacyEMMCPartitionInfo::DoSessionEndCallBack()
1.168 + {
1.169 + OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_ENTRY, this );
1.170 + iDriver->EndInCritical();
1.171 +
1.172 + TInt r = iSession->EpocErrorCode();
1.173 +
1.174 + if (r == KErrNone)
1.175 + r = DecodePartitionInfo();
1.176 +
1.177 + iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
1.178 + OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_EXIT, this );
1.179 + }
1.180 +
1.181 +TInt DLegacyEMMCPartitionInfo::DecodePartitionInfo()
1.182 +//
1.183 +// decode partition info that was read into internal buffer
1.184 +//
1.185 + {
1.186 + OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ENTRY, this );
1.187 + TUint partitionCount=iPartitionInfo->iPartitionCount=0;
1.188 + TInt defaultPartitionNumber=-1;
1.189 + TMBRPartitionEntry* pe;
1.190 + const TUint KMBRFirstPartitionOffsetAligned = KMBRFirstPartitionOffset & ~3;
1.191 + TInt i;
1.192 +
1.193 + // Read of the first sector successful so check for a Master Boot Record
1.194 + if (*(TUint16*)(&iIntBuf[KMBRSignatureOffset])!=0xAA55)
1.195 + {
1.196 + // If no valid signature give up now, No way to re-format an internal drive correctly
1.197 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT1, this, KErrCorrupt );
1.198 + return KErrCorrupt;
1.199 + }
1.200 +
1.201 + __ASSERT_COMPILE(KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry) <= KMBRSignatureOffset);
1.202 +
1.203 + memmove(&iIntBuf[0], &iIntBuf[2],
1.204 + KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry));
1.205 +
1.206 +
1.207 + for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
1.208 + pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
1.209 + {
1.210 + if (pe->IsDefaultBootPartition())
1.211 + {
1.212 + SetPartitionEntry(&iPartitionInfo->iEntry[0],pe->iFirstSector,pe->iNumSectors);
1.213 + defaultPartitionNumber=i;
1.214 + partitionCount++;
1.215 + break;
1.216 + }
1.217 + }
1.218 +
1.219 + // Now add any other partitions
1.220 + for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
1.221 + pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
1.222 + {
1.223 + if (defaultPartitionNumber==i)
1.224 + {
1.225 + // Already sorted
1.226 + }
1.227 +
1.228 + // FAT partition ?
1.229 + else if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition() || pe->IsValidExFATPartition())
1.230 + {
1.231 + SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
1.232 + __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: FAT partition found at sector #%u", pe->iFirstSector));
1.233 + OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_FAT, "FAT partition found at sector #%x", pe->iFirstSector);
1.234 + partitionCount++;
1.235 + }
1.236 +
1.237 + else if (pe->iPartitionType == KPartitionTypeROM)
1.238 + {
1.239 + TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
1.240 + SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
1.241 + partitionEntry.iPartitionType = pe->iPartitionType;
1.242 + partitionCount++;
1.243 +
1.244 + __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeROM found at sector #%u", pe->iFirstSector));
1.245 + OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROM, "KPartitionTypeROM found at sector #%x", pe->iFirstSector);
1.246 + }
1.247 +
1.248 + // ROFS partition ?
1.249 + else if (pe->iPartitionType == KPartitionTypeRofs)
1.250 + {
1.251 +
1.252 +// Don't expose this for normal operation only boot?
1.253 + TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
1.254 + SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
1.255 + partitionEntry.iPartitionType = pe->iPartitionType;
1.256 + __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeRofs found at sector #%u", pe->iFirstSector));
1.257 + OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROFS, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
1.258 + partitionCount++;
1.259 + }
1.260 +
1.261 + // Swap partition ?
1.262 + else if (pe->iPartitionType == KPartitionTypePagedData)
1.263 + {
1.264 + __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypePagedData found at sector #%u", pe->iFirstSector));
1.265 + OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_PAGED, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
1.266 + TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
1.267 + SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
1.268 + partitionEntry.iPartitionType = pe->iPartitionType;
1.269 + partitionCount++;
1.270 + }
1.271 + }
1.272 +
1.273 + // Check the validity of the partition address boundaries
1.274 + // If there is any MBR errors
1.275 + if(partitionCount > 0)
1.276 + {
1.277 + const TInt64 deviceSize = iCard->DeviceSize64();
1.278 + TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1];
1.279 + // Check that the card address space boundary is not exceeded by the last partition
1.280 + if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize)
1.281 + {
1.282 + __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space"));
1.283 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT2, this, KErrCorrupt );
1.284 + return KErrCorrupt;
1.285 + }
1.286 +
1.287 + // More than one partition. Go through all of them
1.288 + if (partitionCount > 0)
1.289 + {
1.290 + for(i=partitionCount-1; i>0; i--)
1.291 + {
1.292 + const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
1.293 + TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
1.294 + // Check if partitions overlap
1.295 + if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
1.296 + {
1.297 + __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions"));
1.298 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT3, this, KErrCorrupt );
1.299 + return KErrCorrupt;
1.300 + }
1.301 + }
1.302 + }
1.303 + }
1.304 +
1.305 + if (defaultPartitionNumber==(-1) && partitionCount==0)
1.306 + {
1.307 + __KTRACE_OPT(KPBUSDRV, Kern::Printf("No Valid Partitions Found!"));
1.308 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT4, this, KErrCorrupt );
1.309 + return KErrCorrupt;
1.310 + }
1.311 +
1.312 + iPartitionInfo->iPartitionCount=partitionCount;
1.313 + iPartitionInfo->iMediaSizeInBytes=iCard->DeviceSize64();
1.314 +
1.315 +#ifdef _DEBUG
1.316 + __KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)",partitionCount));
1.317 + for (TUint x=0; x<partitionCount; x++)
1.318 + __KTRACE_OPT(KPBUSDRV, Kern::Printf(" Partition%d (B:%xH L:%xH)",x,I64LOW(iPartitionInfo->iEntry[x].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[x].iPartitionLen)));
1.319 +#endif
1.320 +
1.321 + //Notify medmmc that partitioninfo is complete.
1.322 + iCallBack.CallBack();
1.323 +
1.324 + OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT5, this, KErrNone );
1.325 + return KErrNone;
1.326 + }
1.327 +
1.328 +
1.329 +void DLegacyEMMCPartitionInfo::SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors)
1.330 +//
1.331 +// auxiliary static function to record partition information in TPartitionEntry object
1.332 +//
1.333 + {
1.334 + OstTraceFunctionEntryExt( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_ENTRY, this );
1.335 + aEntry->iPartitionBaseAddr=aFirstSector;
1.336 + aEntry->iPartitionBaseAddr<<=KDiskSectorShift;
1.337 + aEntry->iPartitionLen=aNumSectors;
1.338 + aEntry->iPartitionLen<<=KDiskSectorShift;
1.339 + aEntry->iPartitionType=KPartitionTypeFAT12;
1.340 + OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_EXIT, this );
1.341 + }
1.342 +
1.343 +// End - DLegacyEMMCPartitionInfo
1.344 +
1.345 +
1.346 +EXPORT_C DEMMCPartitionInfo* CreateEmmcPartitionInfo()
1.347 + {
1.348 + OstTraceFunctionEntry0( _CREATEEMMCPARTITIONINFO_ENTRY );
1.349 + return new DLegacyEMMCPartitionInfo;
1.350 + }
1.351 +
1.352 +DECLARE_STANDARD_EXTENSION()
1.353 + {
1.354 + return KErrNone;
1.355 + }