diff -r 189ece41fa29 -r 9aca3be14c27 kernel/eka/drivers/medmmc/bgahsmmcptn.cpp --- 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 #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(&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; iiEntry[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();