Update contrib.
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Partition Management for Embedded MMC devices
18 #include <drivers/emmcptn.h>
19 #include "OstTraceDefinitions.h"
20 #ifdef OST_TRACE_COMPILER_IN_USE
21 #include "locmedia_ost.h"
23 #pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
25 #include "emmcptnTraces.h"
29 const TInt KDiskSectorShift=9;
31 class DLegacyEMMCPartitionInfo : public DEMMCPartitionInfo
34 DLegacyEMMCPartitionInfo();
35 ~DLegacyEMMCPartitionInfo();
37 virtual TInt Initialise(DMediaDriver* aDriver);
38 virtual TInt PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack);
39 virtual TInt PartitionCaps(TLocDrv& aDrive, TDes8& aInfo);
42 void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
45 static void SessionEndCallBack(TAny* aSelf);
46 void DoSessionEndCallBack();
47 virtual TInt DecodePartitionInfo();
50 DMediaDriver* iDriver;
51 TPartitionInfo* iPartitionInfo;
52 TMMCCallBack iSessionEndCallBack;
53 TMMCCallBack iCallBack; // Where to report the PartitionInfo completion
54 DMMCSession* iSession;
59 DLegacyEMMCPartitionInfo::DLegacyEMMCPartitionInfo()
60 : iSessionEndCallBack(DLegacyEMMCPartitionInfo::SessionEndCallBack, this)
62 OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DLEGACYEMMCPARTITIONINFO_ENTRY );
65 DLegacyEMMCPartitionInfo::~DLegacyEMMCPartitionInfo()
67 OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_ENTRY );
69 OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_DESTRUCTOR_EXIT );
72 TInt DLegacyEMMCPartitionInfo::Initialise(DMediaDriver* aDriver)
74 OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_INITIALISE_ENTRY, this );
77 DMMCSocket* socket = ((DMMCSocket*)((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSocket);
80 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT1, this, KErrNoMemory );
84 DMMCStack* stack = socket->Stack(0);
85 iCard = stack->CardP(((DPBusPrimaryMedia*)(iDriver->iPrimaryMedia))->iSlotNumber);
87 iSession = stack->AllocSession(iSessionEndCallBack);
91 iSession->SetStack(stack);
92 iSession->SetCard(iCard);
94 // this gets used before any access
95 TInt bufLen, minorBufLen;
96 stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
98 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_INITIALISE_EXIT2, this, KErrNone );
102 TInt DLegacyEMMCPartitionInfo::PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack)
104 OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_ENTRY, this );
105 iPartitionInfo = &anInfo;
106 iCallBack = aCallBack;
107 // If media driver is persistent (see EMediaDriverPersistent),
108 // the card may have changed since last power down, so reset CID
109 iSession->SetCard(iCard);
111 iSession->SetupCIMReadBlock(0, iIntBuf);
113 TInt r = iDriver->InCritical();
115 r = iSession->Engage();
118 iDriver->EndInCritical();
120 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONINFO_EXIT, this, r );
124 TInt DLegacyEMMCPartitionInfo::PartitionCaps(TLocDrv& aDrive, TDes8& aInfo)
126 OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_ENTRY, this );
127 TLocalDriveCapsV6Buf& Info = static_cast< TLocalDriveCapsV6Buf&> (aInfo);
129 // is this query for the swap partition ?
130 if (aDrive.iPartitionType == KPartitionTypePagedData)
132 Info().iFileSystemId = KDriveFileNone;
133 Info().iDriveAtt|= KDriveAttHidden;
136 // is this query for the ROFS partition ?
137 if (aDrive.iPartitionType == KPartitionTypeRofs)
139 Info().iFileSystemId = KDriveFileSysROFS;
140 Info().iMediaAtt&= ~KMediaAttFormattable;
141 Info().iMediaAtt|= KMediaAttWriteProtected;
144 // is this query for the ROM partition ?
145 if (aDrive.iPartitionType == KPartitionTypeROM)
147 Info().iFileSystemId = KDriveFileNone;
148 Info().iMediaAtt&= ~KMediaAttFormattable;
149 Info().iMediaAtt|= KMediaAttWriteProtected;
152 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_PARTITIONCAPS_EXIT, this, KErrNone );
156 void DLegacyEMMCPartitionInfo::SessionEndCallBack(TAny* aSelf)
158 OstTraceFunctionEntry0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_ENTRY );
159 DLegacyEMMCPartitionInfo& self = *static_cast<DLegacyEMMCPartitionInfo*>(aSelf);
160 self.DoSessionEndCallBack();
161 OstTraceFunctionExit0( DLEGACYEMMCPARTITIONINFO_SESSIONENDCALLBACK_EXIT );
164 void DLegacyEMMCPartitionInfo::DoSessionEndCallBack()
166 OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_ENTRY, this );
167 iDriver->EndInCritical();
169 TInt r = iSession->EpocErrorCode();
172 r = DecodePartitionInfo();
174 iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
175 OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_DOSESSIONENDCALLBACK_EXIT, this );
178 TInt DLegacyEMMCPartitionInfo::DecodePartitionInfo()
180 // decode partition info that was read into internal buffer
183 OstTraceFunctionEntry1( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ENTRY, this );
184 TUint partitionCount=iPartitionInfo->iPartitionCount=0;
185 TInt defaultPartitionNumber=-1;
186 TMBRPartitionEntry* pe;
187 const TUint KMBRFirstPartitionOffsetAligned = KMBRFirstPartitionOffset & ~3;
190 // Read of the first sector successful so check for a Master Boot Record
191 if (*(TUint16*)(&iIntBuf[KMBRSignatureOffset])!=0xAA55)
193 // If no valid signature give up now, No way to re-format an internal drive correctly
194 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT1, this, KErrCorrupt );
198 __ASSERT_COMPILE(KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry) <= KMBRSignatureOffset);
200 memmove(&iIntBuf[0], &iIntBuf[2],
201 KMBRFirstPartitionOffsetAligned + KMBRMaxPrimaryPartitions * sizeof(TMBRPartitionEntry));
204 for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
205 pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
207 if (pe->IsDefaultBootPartition())
209 SetPartitionEntry(&iPartitionInfo->iEntry[0],pe->iFirstSector,pe->iNumSectors);
210 defaultPartitionNumber=i;
216 // Now add any other partitions
217 for (i=0, pe = (TMBRPartitionEntry*)(&iIntBuf[KMBRFirstPartitionOffsetAligned]);
218 pe->iPartitionType != 0 && i < KMaxPartitionEntries; i++,pe--)
220 if (defaultPartitionNumber==i)
226 else if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition() || pe->IsValidExFATPartition())
228 SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
229 __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: FAT partition found at sector #%u", pe->iFirstSector));
230 OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_FAT, "FAT partition found at sector #%x", pe->iFirstSector);
234 else if (pe->iPartitionType == KPartitionTypeROM)
236 TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
237 SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
238 partitionEntry.iPartitionType = pe->iPartitionType;
241 __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeROM found at sector #%u", pe->iFirstSector));
242 OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROM, "KPartitionTypeROM found at sector #%x", pe->iFirstSector);
246 else if (pe->iPartitionType == KPartitionTypeRofs)
249 // Don't expose this for normal operation only boot?
250 TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
251 SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
252 partitionEntry.iPartitionType = pe->iPartitionType;
253 __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypeRofs found at sector #%u", pe->iFirstSector));
254 OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_ROFS, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
259 else if (pe->iPartitionType == KPartitionTypePagedData)
261 __KTRACE_OPT(KLOCDPAGING, Kern::Printf("Mmc: KPartitionTypePagedData found at sector #%u", pe->iFirstSector));
262 OstTrace1(TRACE_INTERNALS, DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_PAGED, "KPartitionTypeRofs found at sector #%x", pe->iFirstSector);
263 TPartitionEntry& partitionEntry = iPartitionInfo->iEntry[partitionCount];
264 SetPartitionEntry(&iPartitionInfo->iEntry[partitionCount],pe->iFirstSector,pe->iNumSectors);
265 partitionEntry.iPartitionType = pe->iPartitionType;
270 // Check the validity of the partition address boundaries
271 // If there is any MBR errors
272 if(partitionCount > 0)
274 const TInt64 deviceSize = iCard->DeviceSize64();
275 TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1];
276 // Check that the card address space boundary is not exceeded by the last partition
277 if(part.iPartitionBaseAddr + part.iPartitionLen > deviceSize)
279 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space"));
280 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT2, this, KErrCorrupt );
284 // More than one partition. Go through all of them
285 if (partitionCount > 0)
287 for(i=partitionCount-1; i>0; i--)
289 const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
290 TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
291 // Check if partitions overlap
292 if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
294 __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions"));
295 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT3, this, KErrCorrupt );
302 if (defaultPartitionNumber==(-1) && partitionCount==0)
304 __KTRACE_OPT(KPBUSDRV, Kern::Printf("No Valid Partitions Found!"));
305 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT4, this, KErrCorrupt );
309 iPartitionInfo->iPartitionCount=partitionCount;
310 iPartitionInfo->iMediaSizeInBytes=iCard->DeviceSize64();
313 __KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)",partitionCount));
314 for (TUint x=0; x<partitionCount; x++)
315 __KTRACE_OPT(KPBUSDRV, Kern::Printf(" Partition%d (B:%xH L:%xH)",x,I64LOW(iPartitionInfo->iEntry[x].iPartitionBaseAddr),I64LOW(iPartitionInfo->iEntry[x].iPartitionLen)));
318 //Notify medmmc that partitioninfo is complete.
319 iCallBack.CallBack();
321 OstTraceFunctionExitExt( DLEGACYEMMCPARTITIONINFO_DECODEPARTITIONINFO_EXIT5, this, KErrNone );
326 void DLegacyEMMCPartitionInfo::SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors)
328 // auxiliary static function to record partition information in TPartitionEntry object
331 OstTraceFunctionEntryExt( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_ENTRY, this );
332 aEntry->iPartitionBaseAddr=aFirstSector;
333 aEntry->iPartitionBaseAddr<<=KDiskSectorShift;
334 aEntry->iPartitionLen=aNumSectors;
335 aEntry->iPartitionLen<<=KDiskSectorShift;
336 aEntry->iPartitionType=KPartitionTypeFAT12;
337 OstTraceFunctionExit1( DLEGACYEMMCPARTITIONINFO_SETPARTITIONENTRY_EXIT, this );
340 // End - DLegacyEMMCPartitionInfo
343 EXPORT_C DEMMCPartitionInfo* CreateEmmcPartitionInfo()
345 OstTraceFunctionEntry0( _CREATEEMMCPARTITIONINFO_ENTRY );
346 return new DLegacyEMMCPartitionInfo;
349 DECLARE_STANDARD_EXTENSION()