--- a/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Fri Jul 09 13:13:20 2010 +0100
+++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Mon Jul 12 14:24:01 2010 +0100
@@ -17,9 +17,10 @@
#include <emmcptn.h>
#include "bgahsmmcptn.h"
-
-const TInt KDiskSectorShift = 9;
-const TUint32 KPIOffsetFromMediaEnd = 1;
+#include "toc.h"
+//#define __DEBUG_PARTITIONS_
+//#define __DEBUG_CHECK_PARTITION_
+const TInt KDiskSectorShift = 9;
class DBB5PartitionInfo : public DEMMCPartitionInfo
{
@@ -36,6 +37,7 @@
void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
private:
+ virtual TInt ReadPartition(TUint32 aPtOffset);
static void SessionEndCallBack(TAny* aSelf);
void DoSessionEndCallBack();
virtual TInt DecodePartitionInfo();
@@ -49,10 +51,13 @@
TMMCard* iCard;
TUint8* iIntBuf;
TUint32 iPartitionAttributes[KMaxLocalDrives];
+ TBool iCheckTOC;
+ Toc* iTocPtr;
};
DBB5PartitionInfo::DBB5PartitionInfo()
- : iSessionEndCallBack(DBB5PartitionInfo::SessionEndCallBack, this)
+ : iSessionEndCallBack(DBB5PartitionInfo::SessionEndCallBack, this),
+ iCheckTOC(EFalse)
{
}
@@ -91,13 +96,19 @@
iPartitionInfo = &aInfo;
iCallBack = aCallBack;
+ // Preferred partition scheme is BB5, which is located in the last block of the media.
+ const TUint32 ptiOffset = (I64LOW(iCard->DeviceSize64() >> KDiskSectorShift)) - KPIOffsetFromMediaEnd;
+ return ReadPartition(ptiOffset);
+ }
+
+TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset)
+ {
// If media driver is persistent (see EMediaDriverPersistent)
// the card may have changed since last power down, so reset CID
iSession->SetCard(iCard);
- const TUint32 ptiOffset = (I64LOW(iCard->DeviceSize64() >> KDiskSectorShift)) - KPIOffsetFromMediaEnd;
- iSession->SetupCIMReadBlock(ptiOffset, iIntBuf);
-
+ iSession->SetupCIMReadBlock(aPtOffset, iIntBuf);
+
TInt r = iDriver->InCritical();
if (r == KErrNone)
r = iSession->Engage();
@@ -117,6 +128,25 @@
Info().iFileSystemId = KDriveFileNone;
Info().iDriveAtt |= KDriveAttHidden;
}
+ else if (aDrive.iPartitionType == KPartitionTypeRofs)
+ {
+ Info().iFileSystemId = KDriveFileSysROFS;
+ Info().iMediaAtt &= ~KMediaAttFormattable;
+ Info().iMediaAtt |= KMediaAttWriteProtected;
+ }
+ else if ((aDrive.iPartitionType == KPartitionTypeROM) ||
+ (aDrive.iPartitionType == KPartitionTypeEmpty))
+ {
+ Info().iFileSystemId = KDriveFileNone;
+ Info().iMediaAtt &= ~KMediaAttFormattable;
+ Info().iMediaAtt |= KMediaAttWriteProtected;
+ }
+ else if ((aDrive.iPartitionType == KPartitionTypePartitionMagic) || //CPS/PMM
+ (aDrive.iPartitionType == KPartitionTypeSymbianCrashLog))
+ {
+ Info().iFileSystemId = KDriveFileNone;
+ Info().iMediaAtt |= KMediaAttFormattable;
+ }
else if ( PartitionIsFAT(aDrive.iPartitionType) || PartitionIsFAT32(aDrive.iPartitionType) )
{
Info().iDriveAtt |= iPartitionAttributes[aDrive.iPartitionNumber];
@@ -140,81 +170,200 @@
if (r == KErrNone)
r = DecodePartitionInfo();
- iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
+ if (!iCheckTOC)
+ {
+ iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
+ }
}
TInt DBB5PartitionInfo::DecodePartitionInfo()
//
-// decode partition info that was read into internal buffer
+// Decode partition info that was read into internal buffer
//
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()"));
TUint partitionCount = iPartitionInfo->iPartitionCount = 0;
- // For internal devices it is only valid to report up to 1 SWAP partition
- TBool foundSwap = EFalse;
+
+ if (iCheckTOC)
+ {
+ // Try utilising the TOC (Table Of Contents) partitioning scheme
+ const TText8* KRofsNames[KNoOfROFSPartitions] = { KTocRofs1Generic,
+ KTocRofs2Generic,
+ KTocRofs3Generic,
+ KTocRofs4Generic,
+ KTocRofs5Generic,
+ KTocRofs6Generic,
+ };
+
+ STocItem item;
+ iTocPtr = reinterpret_cast<Toc*>(&iIntBuf[0]);
+ iTocPtr->iTocStartSector = KTocStartSector;
+ TInt r = KErrNone;
- BGAHSMMCPTN_PI_STR *partitionTable = (BGAHSMMCPTN_PI_STR*)(&iIntBuf[0]);
+// USER Drive - Only 1
+ r = iTocPtr->GetItemByName(KTocUserName, item);
+ if (KErrNone == r)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%X Size = 0x%X", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypeFAT16;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64)item.iStart;
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64)item.iSize;
+ iPartitionAttributes[partitionCount] = 0; // No Additional Attributes required.
+ partitionCount++;
+ }
+
+// ROM Drive
+ r = iTocPtr->GetItemByName(KTocRomGeneric, item);
+ if (KErrNone == r)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%x Size = 0x%x", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypeROM;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);
+ partitionCount++;
+ }
+
+// ROFS
+ for (TUint i = 0; i < KNoOfROFSPartitions; i++)
+ {
+ /* Search ROFSn item */
+ r = iTocPtr->GetItemByName(KRofsNames[i], item);
+ if (r == KErrNone)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%X Size = 0x%X", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypeRofs;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);
+ partitionCount++;
+ }
+ }
- // Verify that this is the Nokia partition table
- if( memcompare( (TUint8*)&(partitionTable->iId[0]), sizeof(BGAHSMMCPTN_PI_ID), (TUint8*)BGAHSMMCPTN_PI_ID, sizeof(BGAHSMMCPTN_PI_ID)) == 0 )
- {
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("Nokia partition structure found"));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->id..............: %s", partitionTable->iId ));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->sector_size.....: %d = 0x%x", partitionTable->iSector_size, partitionTable->iSector_size));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->major_ver.......: %d", partitionTable->iMajor_ver));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->minor_ver.......: %d", partitionTable->iMinor_ver));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->partition_amount: %d", partitionTable->iPartition_amount));
-
-
- TUint8 PartitionType = 0;
- // Check Supported Version is present
- if (partitionTable->iMajor_ver <= BGAHSMMCPTN_PI_VER_MAJOR)
- {
- for( TUint8 index = 0; (index < partitionTable->iPartition_amount) && (index < BGAHSMMCPTN_LAST_DRIVE); index++ )
- {
- if (partitionTable->iMinor_ver >= BGAHSMMCPTN_PART_TYPE_SUPP_VER_MINOR)
- PartitionType = partitionTable->iPartitions[index].iPartition_type;
- else
- PartitionType = partitionTable->iPartitions[index].iPartition_id;
+// CPS Drive - Only 1
+ r = iTocPtr->GetItemByName(KTocCps, item);
+ if (KErrNone == r)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%X Size = 0x%X", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypePartitionMagic;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) item.iSize;
+ partitionCount++;
+ }
+
+// CRASH Drive - Only 1
+ r = iTocPtr->GetItemByName(KTocCrashLog, item);
+ if (KErrNone == r)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%X Size = 0x%X", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypeSymbianCrashLog;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) item.iSize;
+ partitionCount++;
+ }
+
+// SWAP Partition - Only 1
+ r = iTocPtr->GetItemByName(KTocSwap, item);
+ if (KErrNone == r)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD : ] (%11s) in TOC found : Start addr = 0x%X Size = 0x%X", item.iFileName, item.iStart, item.iSize));
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = KPartitionTypePagedData;
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) item.iSize;
+ partitionCount++;
+ }
+
+#ifdef __DEBUG_PARTITIONS_
+ for (TInt i = 0; i<partitionCount; i++)
+ {
+ Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[i].iPartitionType);
+ Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[i].iPartitionBaseAddr >> KDiskSectorShift));
+ Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionLen, iPartitionInfo->iEntry[i].iPartitionLen >> KDiskSectorShift);
+ Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[i]);
+ Kern::Printf(" ");
+ }
+#endif //__DEBUG_PARTITIONS_
+
+ iCheckTOC = EFalse;
+ }
+ else
+ {
+ // Try utilising the BB5 partitioning scheme
+ BGAHSMMCPTN_PI_STR *partitionTable = (BGAHSMMCPTN_PI_STR*)(&iIntBuf[0]);
+
+ // Verify that this is the Nokia partition table
+ if( memcompare( (TUint8*)&(partitionTable->iId[0]), sizeof(BGAHSMMCPTN_PI_ID), (TUint8*)BGAHSMMCPTN_PI_ID, sizeof(BGAHSMMCPTN_PI_ID)) == 0 )
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Nokia partition structure found"));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->id..............: %s", partitionTable->iId ));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->sector_size.....: %d = 0x%x", partitionTable->iSector_size, partitionTable->iSector_size));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->major_ver.......: %d", partitionTable->iMajor_ver));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->minor_ver.......: %d", partitionTable->iMinor_ver));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->partition_amount: %d", partitionTable->iPartition_amount));
- if( (partitionTable->iPartitions[index].iSize > 0) &&
- ( PartitionIsFAT(PartitionType) ||
- PartitionIsFAT32(PartitionType) ||
- (KPartitionTypePagedData == PartitionType && !foundSwap) ) )
- {
- iPartitionInfo->iEntry[partitionCount].iPartitionType = PartitionType;
- iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) partitionTable->iPartitions[index].iStart_sector << KDiskSectorShift;
- iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) partitionTable->iPartitions[index].iSize << KDiskSectorShift;
- iPartitionAttributes[partitionCount] = partitionTable->iPartitions[index].iPartition_attributes;
-
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector ));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift)));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize ));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount]));
- __KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
-
- if(KPartitionTypePagedData == PartitionType)
- {
- foundSwap = ETrue;
+ TUint8 partitionType = 0;
+ // Check Supported Version is present
+ if (partitionTable->iMajor_ver <= BGAHSMMCPTN_PI_VER_MAJOR)
+ {
+ for( TUint8 index = 0; (index < partitionTable->iPartition_amount) && (index < BGAHSMMCPTN_LAST_DRIVE); index++ )
+ {
+ if (partitionTable->iMinor_ver >= BGAHSMMCPTN_PART_TYPE_SUPP_VER_MINOR)
+ partitionType = partitionTable->iPartitions[index].iPartition_type;
+ else
+ partitionType = partitionTable->iPartitions[index].iPartition_id;
+
+ // FAT/PMM/CPS/SWAP/CORE/ROFS/CRASH
+ if( (partitionTable->iPartitions[index].iSize > 0) &&
+ ( PartitionIsFAT(partitionType) ||
+ PartitionIsFAT32(partitionType) ||
+ (KPartitionTypeSymbianCrashLog == partitionType) ||
+ (KPartitionTypePartitionMagic == partitionType) || //CPS/PMM
+ (KPartitionTypeRofs == partitionType) ||
+ (KPartitionTypeEmpty == partitionType) ||
+ (KPartitionTypeROM == partitionType) ||
+ (KPartitionTypePagedData == partitionType) ) )
+ {
+ iPartitionInfo->iEntry[partitionCount].iPartitionType = partitionType;
+ iPartitionAttributes[partitionCount] = partitionTable->iPartitions[index].iPartition_attributes;
+
+ // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS.
+ const TUint32 KstartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0;
+
+ iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) ((partitionTable->iPartitions[index].iStart_sector + KstartOffset) << KDiskSectorShift);
+ iPartitionInfo->iEntry[partitionCount].iPartitionLen = (Int64) ((partitionTable->iPartitions[index].iSize - KstartOffset) << KDiskSectorShift);
+
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector ));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift)));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize ));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount]));
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
+
+ partitionCount++;
}
-
- partitionCount++;
}
- }
- }
- }
-
+ }
+ }
+ else
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("BGAHSMMC signature not found - try TOC layout"));
+ iCheckTOC = ETrue;
+
+ TInt r = ReadPartition(KTocStartSector);
+ return r;
+ }
+ }
+
+
// Validate partition address boundaries
if(partitionCount == 0)
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!"));
return KErrCorrupt;
}
+#ifdef __DEBUG_CHECK_PARTITION_
else
{
// at least one entry for a supported partition found
@@ -242,6 +391,7 @@
}
}
}
+#endif // _DEBUG_CHECK_PARTITION_
iPartitionInfo->iPartitionCount = partitionCount;
iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();