--- a/kernel/eka/bld.inf Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bld.inf Mon Oct 11 19:11:06 2010 +0100
@@ -264,9 +264,13 @@
include/drivers/resmanus_trace.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
include/drivers/i2s.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
- //
+
include/drivers/display.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
+include/drivers/rpmbdevice.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
+include/drivers/rpmbpacket.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
+
+
// Real Time Clock SHAI API
include/drivers/rtclock.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(drivers/)
--- a/kernel/eka/bmarm/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bmarm/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
- Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+ MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bmarm/rpmbextu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+ Close__11DRpmbDevice @ 1 NONAME R3UNUSED ; DRpmbDevice::Close(void)
+ Open__11DRpmbDeviceUi @ 2 NONAME R3UNUSED ; DRpmbDevice::Open(unsigned int)
+ SendAccessRequest__11DRpmbDeviceR5TDes8T1 @ 3 NONAME R3UNUSED ; DRpmbDevice::SendAccessRequest(TDes8 &, TDes8 &)
+ "_._11DRpmbDevice" @ 4 NONAME R3UNUSED ; DRpmbDevice::~DRpmbDevice(void)
+ __11DRpmbDevice @ 5 NONAME R3UNUSED ; DRpmbDevice::DRpmbDevice(void)
+
--- a/kernel/eka/bwins/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bwins/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bwins/rpmbextu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+ ?SendAccessRequest@DRpmbDevice@@QAEHAAVTDes8@@0@Z @ 1 NONAME ; int DRpmbDevice::SendAccessRequest(class TDes8 &, class TDes8 &)
+ ??1DRpmbDevice@@UAE@XZ @ 2 NONAME ; DRpmbDevice::~DRpmbDevice(void)
+ ?Close@DRpmbDevice@@QAEXXZ @ 3 NONAME ; void DRpmbDevice::Close(void)
+ ??0DRpmbDevice@@QAE@XZ @ 4 NONAME ; DRpmbDevice::DRpmbDevice(void)
+ ?Open@DRpmbDevice@@QAEHI@Z @ 5 NONAME ; int DRpmbDevice::Open(unsigned int)
+
--- a/kernel/eka/bx86/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/bx86/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/bx86/rpmbextu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,7 @@
+EXPORTS
+ ??0DRpmbDevice@@QAE@XZ @ 1 NONAME ; public: __thiscall DRpmbDevice::DRpmbDevice(void)
+ ??1DRpmbDevice@@UAE@XZ @ 2 NONAME ; public: virtual __thiscall DRpmbDevice::~DRpmbDevice(void)
+ ?Close@DRpmbDevice@@QAEXXZ @ 3 NONAME ; public: void __thiscall DRpmbDevice::Close(void)
+ ?Open@DRpmbDevice@@QAEHI@Z @ 4 NONAME ; public: int __thiscall DRpmbDevice::Open(unsigned int)
+ ?SendAccessRequest@DRpmbDevice@@QAEHAAVTDes8@@0@Z @ 5 NONAME ; public: int __thiscall DRpmbDevice::SendAccessRequest(class TDes8 &,class TDes8 &)
+
--- a/kernel/eka/drivers/media/base_e32_drivers_media.mrp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/media/base_e32_drivers_media.mrp Mon Oct 11 19:11:06 2010 +0100
@@ -44,6 +44,7 @@
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\eabi\sdcard3c\sdio\epbusmu.def
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\eabi\sdcard3c\sdio\distribution.policy.s60
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\sdio
+source \sf\os\kernelhwsrv\kernel\eka\drivers\rpmb
source \sf\os\kernelhwsrv\kernel\eka\drivers\media
--- a/kernel/eka/drivers/media/bld.inf Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/media/bld.inf Mon Oct 11 19:11:06 2010 +0100
@@ -56,6 +56,7 @@
../../drivers/medmmc/bgahsmmcptn
../../drivers/pbus/mmc/epbusmmc
../../drivers/medmmc/medmmc
+../../drivers/rpmb/rpmbext
#if !defined(WINS) && !defined(GENERIC_X86)
../../drivers/pbus/mmc/sdcard/sdcard3c/epbussd
--- a/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -16,11 +16,13 @@
//
#include <emmcptn.h>
+#include "mmc.h"
#include "bgahsmmcptn.h"
+#include "medmmc.h"
#include "toc.h"
+
//#define __DEBUG_PARTITIONS_
//#define __DEBUG_CHECK_PARTITION_
-const TInt KDiskSectorShift = 9;
class DBB5PartitionInfo : public DEMMCPartitionInfo
{
@@ -39,8 +41,11 @@
private:
virtual TInt ReadPartition(TUint32 aPtOffset);
static void SessionEndCallBack(TAny* aSelf);
- void DoSessionEndCallBack();
+ void DoSessionEndCallBack();
virtual TInt DecodePartitionInfo();
+ TInt GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize);
+ TInt GetPartitionOffset(TUint32& aPtOffset);
+ TInt SelectNextPartition();
protected:
DMediaDriver* iDriver;
@@ -53,6 +58,7 @@
TUint32 iPartitionAttributes[KMaxLocalDrives];
TBool iCheckTOC;
Toc* iTocPtr;
+ TUint32 iSelectedPartition;
};
DBB5PartitionInfo::DBB5PartitionInfo()
@@ -88,19 +94,169 @@
TInt bufLen, minorBufLen;
stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
+ iSelectedPartition = TExtendedCSD::ESelectUserArea;
+
return(KErrNone);
}
TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack)
{
iPartitionInfo = &aInfo;
+ iPartitionInfo->iPartitionCount = 0;
iCallBack = aCallBack;
+ // Always check the user partition first
+ iSelectedPartition = TExtendedCSD::ESelectUserArea;
+ iSession->SetPartition(iSelectedPartition);
+
// 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);
+ TUint32 ptiOffset;
+ TInt r;
+ do
+ {
+ r = GetPartitionOffset(ptiOffset);
+
+ if(r == KErrNone)
+ {
+ r = ReadPartition(ptiOffset);
+ return r;
+ }
+
+ r = SelectNextPartition();
+ }
+ while(r != KErrNotFound);
+
+ return r;
}
+// retrieves size in terms of sectors
+TInt DBB5PartitionInfo::GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize)
+ {
+ TInt r = KErrNone;
+
+ TUint32 size = 0;
+
+ const TExtendedCSD& extCsd = iCard->ExtendedCSD();
+
+ switch(aPartition)
+ {
+ case TExtendedCSD::ESelectUserArea:
+ {
+ size = (TUint32)(iCard->DeviceSize64() / KSectorSize);
+
+ if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
+ {
+ TUint32 otherPartitionsSize =
+ extCsd.GeneralPurposePartition1SizeInSectors()
+ + extCsd.GeneralPurposePartition2SizeInSectors()
+ + extCsd.GeneralPurposePartition3SizeInSectors()
+ + extCsd.GeneralPurposePartition4SizeInSectors();
+
+ __ASSERT_DEBUG(size >= otherPartitionsSize, Kern::Fault("DBB5PartitionInfo size mismatch", __LINE__));
+ size -= otherPartitionsSize;
+ }
+ }
+ break;
+ case TExtendedCSD::ESelectBootPartition1:
+ case TExtendedCSD::ESelectBootPartition2:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_3) ?
+ 0 : extCsd.BootSizeInSectors();
+ break;
+ case TExtendedCSD::ESelectRPMB:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ?
+ 0 : extCsd.RpmbSizeInSectors();
+ break;
+ case TExtendedCSD::ESelectGPAPartition1:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ?
+ 0 : extCsd.GeneralPurposePartition1SizeInSectors();
+ break;
+ case TExtendedCSD::ESelectGPAPartition2:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ?
+ 0 : extCsd.GeneralPurposePartition2SizeInSectors();
+ break;
+ case TExtendedCSD::ESelectGPAPartition3:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ?
+ 0 : extCsd.GeneralPurposePartition3SizeInSectors();
+ break;
+ case TExtendedCSD::ESelectGPAPartition4:
+ size = (extCsd.ExtendedCSDRev() < TExtendedCSD::EExtendedCSDRev1_5) ?
+ 0 : extCsd.GeneralPurposePartition4SizeInSectors();
+ break;
+ default:
+ // unknown partition
+ size = 0;
+ r = KErrNotSupported;
+ break;
+ }
+
+ aSize = size;
+ return r;
+ }
+
+TInt DBB5PartitionInfo::GetPartitionOffset(TUint32& aPtiOffset)
+ {
+ TInt r = GetPartitionSizeInSectors(iSelectedPartition, aPtiOffset);
+
+ if((r != KErrNone) || (aPtiOffset == 0))
+ {
+ // error reading or partition not supported, skip
+ r = KErrNotSupported;
+ }
+ else
+ {
+ // need to determine correct end of the partition
+ aPtiOffset -= KPIOffsetFromMediaEnd;
+ }
+
+ return r;
+ }
+
+TInt DBB5PartitionInfo::SelectNextPartition()
+ {
+ TExtendedCSD extCsd = iCard->ExtendedCSD();
+ TUint maxPartition = TExtendedCSD::ESelectUserArea;
+
+ if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
+ {
+ // v4.4 supports UDA, 2x BOOT, RPMB and 4x GPAP partitions
+ maxPartition = TExtendedCSD::ESelectGPAPartition4;
+ }
+#ifdef EMMC_BOOT_PARTITION_ACCESS_ENABLED
+ else if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_3)
+ {
+ // v4.3 supports up to two BOOT partitions
+ maxPartition = TExtendedCSD::ESelectBootPartition2;
+ }
+#endif // EMMC_BOOT_PARTITION_ACCESS_ENABLED
+
+ ++iSelectedPartition;
+
+ // skip through to GPAP1 if either the currently selected partition is RPMB or
+ // if it is one of the BOOT partitions and boot partition access is not enabled
+ if((iSelectedPartition == TExtendedCSD::ESelectRPMB)
+#ifndef EMMC_BOOT_PARTITION_ACCESS_ENABLED
+ || (iSelectedPartition == TExtendedCSD::ESelectBootPartition1)
+ || (iSelectedPartition == TExtendedCSD::ESelectBootPartition2)
+#endif
+ )
+ {
+ iSelectedPartition = TExtendedCSD::ESelectGPAPartition1;
+ }
+
+ TInt r = KErrNone;
+ if(iSelectedPartition > maxPartition)
+ {
+ r = KErrNotFound; // no more partitions to be checked
+ }
+ else
+ {
+ iSession->SetPartition(iSelectedPartition);
+ }
+
+ return r;
+ }
+
+// returns KErrCompletion on success after having checked all partitions
TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset)
{
// If media driver is persistent (see EMediaDriverPersistent)
@@ -167,24 +323,82 @@
TInt r = iSession->EpocErrorCode();
+
+ TInt& partitionCount = iPartitionInfo->iPartitionCount;
+
if (r == KErrNone)
r = DecodePartitionInfo();
- if (!iCheckTOC)
- {
- iDriver->PartitionInfoComplete(r == KErrNone ? r : KErrNotReady);
- }
+ if (iCheckTOC)
+ {
+ //BB5 table not found need to check for TOC in this partition before continuing
+ if (r!=KErrNone)
+ {
+ iDriver->PartitionInfoComplete(KErrNotReady);
+ }
+ return;
+ }
+
+
+ if(r == KErrNone)
+ {
+ // check next partition(s) for BB5
+ TUint32 ptiOffset = 0;
+
+ r = SelectNextPartition();
+ while(r != KErrNotFound)
+ {
+ if(r == KErrNone)
+ r = GetPartitionOffset(ptiOffset);
+
+ if(r == KErrNone)
+ {
+ r = ReadPartition(ptiOffset);
+ if(r != KErrNone)
+ break;
+
+
+ return;
+ }
+
+ r = SelectNextPartition();
+ }
+
+
+ // end of partitions - reinterpret error code
+ if(r != KErrNotFound)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: ReadPartition() failed r=%d!", r));
+ r = KErrCorrupt;
+ }
+ else if(partitionCount == 0)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: No supported partitions found!"));
+ r = KErrCorrupt;
+ }
+ else
+ r = KErrCompletion;
+ }
+
+ // Notify medmmc that partitioninfo is complete
+ iCallBack.CallBack();
+
+ // All potential partitions checked - KErrCompletion
+ // indicates that there are no more partitions to check
+ r = (r == KErrCompletion) ? KErrNone : KErrNotReady;
+ iDriver->PartitionInfoComplete(r);
}
+
TInt DBB5PartitionInfo::DecodePartitionInfo()
//
// Decode partition info that was read into internal buffer
//
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()"));
- TUint partitionCount = iPartitionInfo->iPartitionCount = 0;
+ TInt& partitionCount = iPartitionInfo->iPartitionCount;
+ TInt r = KErrNone;
-
if (iCheckTOC)
{
// Try utilising the TOC (Table Of Contents) partitioning scheme
@@ -199,7 +413,6 @@
STocItem item;
iTocPtr = reinterpret_cast<Toc*>(&iIntBuf[0]);
iTocPtr->iTocStartSector = KTocStartSector;
- TInt r = KErrNone;
// USER Drive - Only 1
r = iTocPtr->GetItemByName(KTocUserName, item);
@@ -262,7 +475,7 @@
}
// SWAP Partition - Only 1
- r = iTocPtr->GetItemByName(KTocSwap, item);
+ 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));
@@ -283,6 +496,7 @@
}
#endif //__DEBUG_PARTITIONS_
+ r = KErrNone;
iCheckTOC = EFalse;
}
else
@@ -324,12 +538,12 @@
{
iPartitionInfo->iEntry[partitionCount].iPartitionType = partitionType;
iPartitionAttributes[partitionCount] = partitionTable->iPartitions[index].iPartition_attributes;
-
+ static_cast<DMmcMediaDriverFlash *>(iDriver)->SetEMmcPartitionMapping(partitionCount, iSelectedPartition);
// 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;
+ 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;
+ 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));
@@ -339,6 +553,7 @@
__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("iPartitionMapping.: 0x%x", static_cast<DMmcMediaDriverFlash *>(iDriver)->GetEMmcPartitionMapping(partitionCount)));
__KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
partitionCount++;
@@ -361,24 +576,43 @@
if(partitionCount == 0)
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!"));
- return KErrCorrupt;
+ // No Supported partitions found on this physical partition
+ return KErrNone;
}
-#ifdef __DEBUG_CHECK_PARTITION_
- else
+
+#ifdef __DEBUG_CHECK_PARTITION_
+ // Validate partition address boundaries
+ TUint32 eMmcPartitionSizeInSectors = 0;
+ if(r == KErrNone)
{
- // at least one entry for a supported partition found
- const TInt64 deviceSize = iCard->DeviceSize64();
+ // At least one entry for a supported partition found
+ r = GetPartitionSizeInSectors(iSelectedPartition, eMmcPartitionSizeInSectors);
+
+ if(r != KErrNone)
+ {
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Could not retrieve size for eMMC partition 0x%02X", iSelectedPartition));
+ r = KErrCorrupt;
+ }
+ }
+
+ if(r == KErrNone)
+ {
+ TUint64 eMmcPartitionSize = eMmcPartitionSizeInSectors * KSectorSize;
+
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)
+
+ // Check that the eMmcPartition address space boundary is not exceeded by the last partition
+ if(part.iPartitionBaseAddr + part.iPartitionLen > eMmcPartitionSize)
{
- __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: MBR partition exceeds card memory space"));
- return KErrCorrupt;
+ __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Partition #%d exceeds eMmc address space", partitionCount));
+ r = KErrCorrupt;
}
-
- // Go through all partition entries and check boundaries
- for(TInt i = partitionCount - 1; i > 0; i--)
+ }
+
+ if(r == KErrNone)
+ {
+ // Go through all BB5 partition entries on this eMMC partition and check boundaries
+ for(TInt i = partitionCount - 1; i > iPartitionInfo->iPartitionCount; i--)
{
const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
@@ -387,20 +621,20 @@
if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
{
__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions - check #%d", i));
- return KErrCorrupt;
+ r = KErrCorrupt;
}
}
}
#endif // _DEBUG_CHECK_PARTITION_
-
- iPartitionInfo->iPartitionCount = partitionCount;
- iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
-
- //Notify medmmc that partitioninfo is complete.
- iCallBack.CallBack();
+
+ if(r == KErrNone)
+ {
+ iPartitionInfo->iPartitionCount = partitionCount;
+ iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
+ }
__KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)", partitionCount));
- return KErrNone;
+ return r;
}
--- a/kernel/eka/drivers/medmmc/bgahsmmcptn.mmp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/bgahsmmcptn.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -15,11 +15,17 @@
//
//
+// Define this macro to enable access to eMMC BOOT partitions (v4.3 and higher)
+//macro EMMC_BOOT_PARTITION_ACCESS_ENABLED
+
+#include "drivers/elocd.mmh"
+
target bgahsmmcptn.dll
targettype kext
#include "../../kernel/kern_ext.mmh"
systeminclude ../../include/drivers
+userinclude traces
source bgahsmmcptn.cpp
source toc.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bmarm/medmmcu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+ CreatePhysicalDevice__Fv @ 1 NONAME R3UNUSED ; CreatePhysicalDevice(void)
+ KTRIMEnabled @ 2 NONAME ; (null)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bwins/medmmcu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+ ?CreatePhysicalDevice@@YAPAVDPhysicalDevice@@XZ @ 1 NONAME ; class DPhysicalDevice * CreatePhysicalDevice(void)
+ ?KTRIMEnabled@@3IB @ 2 NONAME ; unsigned int const KTRIMEnabled
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/bx86/medmmcu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,4 @@
+EXPORTS
+ ?CreatePhysicalDevice@@YAPAVDPhysicalDevice@@XZ @ 1 NONAME ; class DPhysicalDevice * CreatePhysicalDevice(void)
+ ?KTRIMEnabled@@3IB @ 2 NONAME ; unsigned int const KTRIMEnabled
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/eabi/medmmcu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,8 @@
+EXPORTS
+ _Z20CreatePhysicalDevicev @ 1 NONAME
+ KTRIMEnabled @ 2 NONAME DATA 4
+ _ZTI20DMmcMediaDriverFlash @ 3 NONAME
+ _ZTI28DPhysicalDeviceMediaMmcFlash @ 4 NONAME
+ _ZTV20DMmcMediaDriverFlash @ 5 NONAME
+ _ZTV28DPhysicalDeviceMediaMmcFlash @ 6 NONAME
+
--- a/kernel/eka/drivers/medmmc/medmmc.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/medmmc.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -50,6 +50,7 @@
#define __ASSERT_CACHE(c,p)
#endif
+#include "medmmc.h"
GLREF_C TInt GetMediaDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry, TUint16& aReservedSectors, const TMMCard* aCardP);
GLREF_C TBool MBRMandatory(const TMMCard* aCardP);
@@ -59,11 +60,10 @@
extern TInt GetCardFormatInfo(const TMMCard* aCardP, TLocalDriveCapsV5& aCaps);
+IMPORT_C extern const TUint KTRIMEnabled;
+
const TInt KStackNumber = 0;
-const TInt KDiskSectorSize=512;
-const TInt KDiskSectorShift=9;
-
const TInt KIdleCurrentInMilliAmps = 1;
const TInt KMBRFirstPartitionEntry=0x1BE;
@@ -90,237 +90,6 @@
const TInt64 KInvalidBlock = -1;
const TInt KNoCacheBlock = -1;
-class DMmcMediaDriverFlash : public DMediaDriver
- {
-public:
- DMmcMediaDriverFlash(TInt aMediaId);
- ~DMmcMediaDriverFlash();
- // ...from DMediaDriver
- virtual void Close();
- // replacing pure virtual
- virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*);
- virtual TInt Request(TLocDrvRequest& aRequest);
- virtual TInt PartitionInfo(TPartitionInfo& anInfo);
- virtual void NotifyPowerDown();
- virtual void NotifyEmergencyPowerDown();
- // For creation by DPhysicalDeviceMediaMmcFlash
- TInt DoCreate(TInt aMediaId);
-
-private:
- enum TPanic
- {
- EDRInUse = 0x0000, EDRStart, EDRNotPositive, EDREnd,
- ELRRequest = 0x0010, ELRStart, ELRNotPositive, ELREnd, ELRCached,
- EDWInUse = 0x0020, EDWStart, EDWNotPositive, EDWEnd,
- EDFInUse = 0x0030, EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket,
- ELWRequest = 0x0040, ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign,
- ELWLength, ELFStart, ELFEnd, ELFNotPositive,
- ERPIInUse = 0x0050,
- EPCInUse = 0x0060, EPCFunc,
- ESECBQueued = 0x0070,
- EDSEDRequest = 0x0080, EDSEDNotErrComplete,
- ECRReqIdle = 0x0090, ECRRequest,
- ERRBStAlign = 0x00a0, ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos,
- ERRBOverflow, ERRBCchInv, ERRBExist,
- ERWBStPos = 0x00b0, ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv,
- EMBStPos = 0x00c0, EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign,
- EMBOverflow, EMBCchInvPre, EMBCchInvPost,
- EBGAStPos = 0x00d0, EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign,
- EBGAOverflow, EBGACchInv,
- EICMNegative = 0x00e0, EICMOverflow, ECMIOverflow,
- EGCBAlign = 0x00f0, EGCBPos, EGCBCchInv,
-
- ECFSessPtrNull = 0x0100, // Code Fault - session pointer NULL
-
- EDBNotEven = 0x0110, // Not and even number of blocks in the buffer cache
- EDBCBQueued = 0x0111, // The data transfer callback is already queued
- EDBLength = 0x0112, // The length of data to transfer in data transfer callback is not positive
- EDBLengthTooBig = 0x0113, // The length of data to transfer in data transfer callback is too big
- EDBOffsetTooBig = 0x0114, // The Offset into the user data buffer is too big
- EDBCacheInvalid = 0x0115, // The cache is invalid at the end of data transfer
- EDBNotOptimal = 0x0116, // Due to Cache size DB functionality will never be utilised
- ENoDBSupport = 0x0120, // DMA request arrived but PSL does not support double buffering
- ENotDMAAligned = 0x0121,
- };
- static void Panic(TPanic aPnc);
-
- enum TMediaRequest
- {
- EMReqRead = 0,
- EMReqWrite = 1,
- EMReqFormat = 2,
- EMReqPtnInfo,
- EMReqPswdCtrl,
- EMReqForceErase,
- EMReqUpdatePtnInfo,
- EMReqWritePasswordData,
- EMReqIdle,
- EMReqEMMCPtnInfo,
- };
- enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd};
-
- enum {KWtRBMFst = 0x00000001, // iWtRBM - Read First Block only
- KWtRBMLst = 0x00000002, // iWtRBM - Read Last Block only
- KWtMinFst = 0x00000004, // iWtRBM - Write First Block only
- KWtMinLst = 0x00000008, // iWtRBM - Write Last Block only
- KIPCSetup = 0x00000010, // iRdROB - IPC Setup Next Iteration
- KIPCWrite = 0x00000020}; // iRdROB - IPC Write Next Iteration
-
-private:
- // MMC device specific stuff
- TInt DoRead();
- TInt DoWrite();
- TInt DoFormat();
- TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo);
-
- inline DMMCStack& Stack() const;
- inline TInt CardNum() const;
- inline TMediaRequest CurrentRequest() const;
-
- TInt LaunchRead(TInt64 aStart, TUint32 aLength);
- TInt LaunchDBRead();
- TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength);
-
- TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq);
- TInt LaunchFormat(TInt64 aStart, TUint32 aLength);
-
- TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData);
- TInt LaunchRPIRead();
- TInt LaunchRPIErase();
- TInt DecodePartitionInfo();
- TInt WritePartitionInfo();
- TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry);
- TInt CreateDefaultPartition();
-
-
-#if defined __TEST_PAGING_MEDIA_DRIVER__
- TInt HandleControlIORequest();
-#endif
-
- static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
-
- TInt CheckDevice(TMediaReqType aReqType);
-
- static void SessionEndCallBack(TAny* aMediaDriver);
- static void SessionEndDfc(TAny* aMediaDriver);
- void DoSessionEndDfc();
-
- static void DataTransferCallBack(TAny* aMediaDriver);
- static void DataTransferCallBackDfc(TAny* aMediaDriver);
-
- void DoReadDataTransferCallBack();
- void DoWriteDataTransferCallBack();
- void DoPhysReadDataTransferCallBack();
- void DoPhysWriteDataTransferCallBack();
-
- TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength);
- TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength);
- void PrepareNextPhysicalFragment();
-
- TInt EngageAndSetReadRequest(TMediaRequest aRequest);
- TInt EngageAndSetWriteRequest(TMediaRequest aRequest);
- TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent);
- void CompleteRequest(TInt aReason);
-
- TInt ReadDataUntilCacheExhausted(TBool* aAllDone);
- TInt WriteDataToUser(TUint8* aBufPtr);
- TInt ReadDataFromUser(TDes8& aDes, TInt aOffset);
- TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength);
- TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM);
- void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex);
- void BuildGammaArray(TInt64 aStart, TInt64 aEnd);
- void InvalidateCache();
- void InvalidateCache(TInt64 aStart, TInt64 aEnd);
- TUint8* IdxToCchMem(TInt aIdx) const;
- TInt CchMemToIdx(TUint8* aMemP) const;
-
- TInt DoPasswordOp();
- void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData);
- void Reset();
- TInt AllocateSession();
-
-#ifdef _DEBUG_CACHE
- TBool CacheInvariant();
- TUint8* GetCachedBlock(TInt64 aAddr);
-#endif
-private:
- DMMCStack* iStack; // controller objects
- TMMCard* iCard;
- DMMCSession* iSession;
- DMMCSocket* iSocket;
-
- TInt iCardNumber;
-
- TUint iBlkLenLog2; // cached CSD data
- TUint32 iBlkLen;
- TInt64 iBlkMsk;
- TBool iReadBlPartial;
- TUint32 iPrWtGpLen; // preferred write group size in bytes,
- TInt64 iPrWtGpMsk;
-
- TInt iReadCurrentInMilliAmps; // power management
- TInt iWriteCurrentInMilliAmps;
-
- TUint8* iMinorBuf; // MBR, CMD42, partial read
- TUint8* iCacheBuf; // cached buffer
- TUint32 iMaxBufSize;
- TInt iBlocksInBuffer;
- TInt64* iCachedBlocks;
- TInt* iGamma; // B lookup, ReserveReadBlocks()
- TUint8* iIntBuf; // start of current buffer region
- TInt iLstUsdCchEnt; // index of last used cache entry
-
- TLocDrvRequest* iCurrentReq; // Current Request
- TMediaRequest iMedReq;
-
- TInt64 iReqStart; // user-requested start region
- TInt64 iReqCur; // Currently requested start region
- TInt64 iReqEnd; // user-requested end region
- TInt64 iPhysStart; // physical region for one operation
- TInt64 iPhysEnd; // physical end point for one operation
- TInt64 iDbEnd; // Double buffer end point for one operation
-
- TUint64 iEraseUnitMsk;
-
- TUint iWtRBM; // Write - Read Before Modify Flags
- TUint iRdROB; // Read - Read Odd Blocks Flags
-
- TInt iFragOfset;
- TUint32 iIPCLen;
- TUint32 iNxtIPCLen;
- TUint32 iBufOfset;
-
- TUint iHiddenSectors; // bootup / password
-
- TMMCCallBack iSessionEndCallBack;
- TDfc iSessionEndDfc;
-
- TPartitionInfo* iPartitionInfo;
- TMMCMediaTypeEnum iMediaType;
- TMMCEraseInfo iEraseInfo;
- TBool iMbrMissing;
- TInt iMediaId;
-
- DMMCStack::TDemandPagingInfo iDemandPagingInfo;
-
-#if defined(__TEST_PAGING_MEDIA_DRIVER__)
- SMmcStats iMmcStats;
-#endif // __TEST_PAGING_MEDIA_DRIVER__
-
- TMMCCallBack iDataTransferCallBack; // Callback registered with the MMC stack to perform double-buffering
- TDfc iDataTransferCallBackDfc; // ...and the associated DFC queue.
-
- TBool iSecondBuffer; // Specified the currently active buffer
- TBool iDoLastRMW; // ETrue if the last double-buffer transfer requires RMW modification
- TBool iDoDoubleBuffer; // ETrue if double-buffering is currently active
- TBool iDoPhysicalAddress; // ETrue if Physical Addressing is currently active
- TBool iCreateMbr;
- TBool iReadToEndOfCard; // {Read Only} ETrue if Reading to end of Card
-
- TBool iInternalSlot;
-
- DEMMCPartitionInfo* iMmcPartitionInfo; // Responsible for decoding partitions for embedded devices
- };
// ======== DPhysicalDeviceMediaMmcFlash ========
@@ -471,6 +240,10 @@
// NB aMedia Id = the media ID of the primary media, iMediaId = the media ID of this media
__KTRACE_OPT(KPBUSDRV, Kern::Printf("DMmcMediaDriverFlash(), iMediaId %d, aMediaId %d\n", iMediaId, aMediaId));
OstTraceExt2( TRACE_FLOW, DMMCMEDIADRIVERFLASH_DMMCMEDIADRIVERFLASH, "> DMmcMediaDriverFlash::DMmcMediaDriverFlash;aMediaId=%d;iMediaId=%d", (TInt) aMediaId, (TInt) iMediaId );
+ for(TInt drv = 0; drv < KMaxLocalDrives; drv++)
+ {
+ SetEMmcPartitionMapping(drv, TExtendedCSD::ESelectUserArea);
+ }
}
@@ -540,12 +313,13 @@
iMinorBuf = buf;
+ // reserve KRpmbOneFramePacketLength bytes after the minor buffer for RPMB requests / responses
// cache buffer can use rest of blocks in buffer. Does not have to be power of 2.
- iCacheBuf = iMinorBuf + minorBufLen;
+ iCacheBuf = iMinorBuf + minorBufLen + KRpmbOneFramePacketLength;
// We need to devide up the buffer space between the media drivers.
// The number of buffer sub-areas = number of physical card slots * number of media
- bufLen-= minorBufLen;
+ bufLen-= (minorBufLen + KRpmbOneFramePacketLength);
DPBusPrimaryMedia* primaryMedia = (DPBusPrimaryMedia*) iPrimaryMedia;
TInt physicalCardSlots = iStack->iMaxCardsInStack;
TInt numMedia = primaryMedia->iLastMediaId - primaryMedia->iMediaId + 1;
@@ -1160,7 +934,8 @@
}
// Now, if the erase start/end points are aligned to a min. erase unit boundary, we can use an erase cmd.
- if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0)
+ if ((iPhysStart & minEraseSecMsk) == 0 && (iPhysEnd & minEraseSecMsk) == 0 ||
+ (iCurrentReq->Id() == DLocalDrive::EDeleteNotify && (iPhysStart - iPhysEnd) % KMMCardHighCapBlockSize == 0 )) // handle TRIM case where erase is aligned to 512 blocks
{
// Aligned erase
// Check that erase commands are supported prior to issuing an erase command
@@ -1174,6 +949,10 @@
iSession->SetupCIMEraseMSector(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2),
I64LOW((iPhysEnd - iPhysStart) >> KMMCardHighCapBlockSizeLog2)); // Use ACMD32/33/38 (Erase Sector)
}
+ if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify)
+ {
+ iSession->Command().iFlags|= KMMCCmdFlagDeleteNotify; //set flags for Trim
+ }
}
else
{
@@ -1200,7 +979,7 @@
memset (iCacheBuf, 0x00, writeLen);
iSession->SetupCIMWriteBlock(I64LOW(iPhysStart >> KMMCardHighCapBlockSizeLog2), iCacheBuf, writeLen >> KMMCardHighCapBlockSizeLog2);
}
-
+
r = EngageAndSetWriteRequest(EMReqFormat);
}
OstTraceFunctionExitExt( DMMCMEDIADRIVERFLASH_LAUNCHFORMAT_EXIT, this, r );
@@ -2307,6 +2086,10 @@
{
iReqCur = iPhysEnd;
}
+ else if(iCurrentReq->Id() == DLocalDrive::EDeleteNotify) //handle DeleteNotify case
+ {
+ iReqCur = iPhysEnd;
+ }
else
{
// Formating to a mis-aligned boundary, so we can't make best use of
@@ -2727,9 +2510,25 @@
iMedReq = aRequest;
SetCurrentConsumption(aCurrent);
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED
+ if((iSession->Partition() & TExtendedCSD::EPartitionTestMode) != 0)
+ {
+ // driver in test mode, target partition must be set by ControlIO() KMmcSwitchPartition
+ }
+ else
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED
+ if (iCurrentReq)
+ // if iCurrentReq is NULL then it is assuned to be a request for a removable drive
+ // multiple physical partitions are not supported on removable drives hence partition settting is not requied
+ {
+ TInt ptn = iCurrentReq->Drive()->iPartitionNumber;
+ TInt eMmcPtn = GetEMmcPartitionMapping(ptn);
+ iSession->SetPartition(eMmcPtn);
+ }
+
// Reset the card pointer just in case the stack has changed it.
iSession->SetCard(iCard);
-
+
TInt r = InCritical();
if (r == KErrNone)
{
@@ -2783,6 +2582,9 @@
aInfo.iConnectionBusType = EConnectionBusInternal;
aInfo.iDriveAtt = KDriveAttLocal;
aInfo.iMediaAtt = KMediaAttFormattable;
+
+ if(iCard->ExtendedCSD().ExtendedCSDRev() >= 5 && KTRIMEnabled) //TRIM support for v4.4+
+ aInfo.iMediaAtt |= KMediaAttDeleteNotify;
if(iCard->iFlags & KMMCardIsLockable)
aInfo.iMediaAtt |= KMediaAttLockable;
@@ -2899,6 +2701,8 @@
#if defined(__DEMAND_PAGING__) && !defined(__WINS__)
|| DMediaPagingDevice::PageInRequest(*iCurrentReq)
#endif //DEMAND_PAGING
+ // partition switching
+ || (GetEMmcPartitionMapping(iCurrentReq->Drive()->iPartitionNumber) != iSession->Partition())
)
{
*aAllDone = EFalse;
@@ -3745,6 +3549,12 @@
}
r=DoWrite();
break;
+ case DLocalDrive::EDeleteNotify:
+ if(iCard->ExtendedCSD().ExtendedCSDRev() <5)
+ {
+ r=KErrNotSupported;
+ break;
+ }
case DLocalDrive::EFormat:
if (readOnly)
{
@@ -3908,6 +3718,13 @@
break;
}
+#ifdef EMMC_PARTITION_TEST_MODE_ENABLED
+ case KMmcSwitchPartition:
+ __ASSERT_DEBUG(iSession != NULL, Panic(ECFSessPtrNull));
+ InvalidateCache();
+ iSession->SetPartition((TInt) aParam1);
+ break;
+#endif // EMMC_PARTITION_TEST_MODE_ENABLED
default:
r=KErrNotSupported;
break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/medmmc.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,295 @@
+// Copyright (c) 2010 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:
+// drivers/medmmc/medmmc.h
+//
+//
+
+#ifndef MEDMMC_H
+#define MEDMMC_H
+
+#include <drivers/locmedia.h>
+#include <e32const.h>
+
+#if defined(__DEMAND_PAGING__)
+ // If in debug mode, enable paging stats and their retrieval using DLocalDrive::EControlIO
+ #if defined( _DEBUG)
+ #define __TEST_PAGING_MEDIA_DRIVER__
+ #endif
+ #include "mmcdp.h"
+#endif
+
+// Enable this macro to debug cache:
+// NB The greater the number of blocks, the slower this is...
+//#define _DEBUG_CACHE
+#ifdef _DEBUG_CACHE
+#define __ASSERT_CACHE(c,p) (void)((c)||(p,0))
+#else
+#define __ASSERT_CACHE(c,p)
+#endif
+
+const TInt KDiskSectorSize = 512;
+const TInt KDiskSectorShift = 9;
+
+
+class DMmcMediaDriverFlash : public DMediaDriver
+ {
+public:
+ DMmcMediaDriverFlash(TInt aMediaId);
+ ~DMmcMediaDriverFlash();
+ // ...from DMediaDriver
+ virtual void Close();
+ // replacing pure virtual
+ virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage*);
+ virtual TInt Request(TLocDrvRequest& aRequest);
+ virtual TInt PartitionInfo(TPartitionInfo& anInfo);
+ virtual void NotifyPowerDown();
+ virtual void NotifyEmergencyPowerDown();
+ // For creation by DPhysicalDeviceMediaMmcFlash
+ TInt DoCreate(TInt aMediaId);
+
+
+private:
+ enum TPanic
+ {
+ EDRInUse = 0x0000, EDRStart, EDRNotPositive, EDREnd,
+ ELRRequest = 0x0010, ELRStart, ELRNotPositive, ELREnd, ELRCached,
+ EDWInUse = 0x0020, EDWStart, EDWNotPositive, EDWEnd,
+ EDFInUse = 0x0030, EDFStart, EDFNotPositive, EDFEnd, ENotMmcSocket,
+ ELWRequest = 0x0040, ELWStart, ELWFmtStAlign, ELWNotPositive, ELWEnd, ELWFmtEndAlign,
+ ELWLength, ELFStart, ELFEnd, ELFNotPositive,
+ ERPIInUse = 0x0050,
+ EPCInUse = 0x0060, EPCFunc,
+ ESECBQueued = 0x0070,
+ EDSEDRequest = 0x0080, EDSEDNotErrComplete,
+ ECRReqIdle = 0x0090, ECRRequest,
+ ERRBStAlign = 0x00a0, ERRBStPos, ERRBNotPositive, ERRBEndAlign, ERRBEndPos,
+ ERRBOverflow, ERRBCchInv, ERRBExist,
+ ERWBStPos = 0x00b0, ERWBNotPositive, ERWBEndPos, ERWBOverflow, ERWBCchInv,
+ EMBStPos = 0x00c0, EMBStAlign, EMBNotPositive, EMBEndPos, EMBEndAlign,
+ EMBOverflow, EMBCchInvPre, EMBCchInvPost,
+ EBGAStPos = 0x00d0, EBGAStAlign, EBGANotPositive, EBGAEndPos, EBGAEndAlign,
+ EBGAOverflow, EBGACchInv,
+ EICMNegative = 0x00e0, EICMOverflow, ECMIOverflow,
+ EGCBAlign = 0x00f0, EGCBPos, EGCBCchInv,
+
+ ECFSessPtrNull = 0x0100, // Code Fault - session pointer NULL
+
+ EDBNotEven = 0x0110, // Not and even number of blocks in the buffer cache
+ EDBCBQueued = 0x0111, // The data transfer callback is already queued
+ EDBLength = 0x0112, // The length of data to transfer in data transfer callback is not positive
+ EDBLengthTooBig = 0x0113, // The length of data to transfer in data transfer callback is too big
+ EDBOffsetTooBig = 0x0114, // The Offset into the user data buffer is too big
+ EDBCacheInvalid = 0x0115, // The cache is invalid at the end of data transfer
+ EDBNotOptimal = 0x0116, // Due to Cache size DB functionality will never be utilised
+ ENoDBSupport = 0x0120, // DMA request arrived but PSL does not support double buffering
+ ENotDMAAligned = 0x0121,
+ EArrayBoundsExc = 0x0122 // Array bounds exceeded (either too small or too large)
+ };
+ static void Panic(TPanic aPnc);
+
+ enum TMediaRequest
+ {
+ EMReqRead = 0,
+ EMReqWrite = 1,
+ EMReqFormat = 2,
+ EMReqPtnInfo,
+ EMReqPswdCtrl,
+ EMReqForceErase,
+ EMReqUpdatePtnInfo,
+ EMReqWritePasswordData,
+ EMReqIdle,
+ EMReqEMMCPtnInfo,
+ };
+ enum TMediaReqType {EMReqTypeNormalRd,EMReqTypeNormalWr,EMReqTypeUnlockPswd,EMReqTypeChangePswd};
+
+ enum {KWtRBMFst = 0x00000001, // iWtRBM - Read First Block only
+ KWtRBMLst = 0x00000002, // iWtRBM - Read Last Block only
+ KWtMinFst = 0x00000004, // iWtRBM - Write First Block only
+ KWtMinLst = 0x00000008, // iWtRBM - Write Last Block only
+ KIPCSetup = 0x00000010, // iRdROB - IPC Setup Next Iteration
+ KIPCWrite = 0x00000020}; // iRdROB - IPC Write Next Iteration
+
+public:
+ inline void SetEMmcPartitionMapping(TInt aLocalPtn, TInt aEMmcPtn)
+ {
+ __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+ iEMmcPartitionMappings[aLocalPtn] = aEMmcPtn;
+ };
+
+ inline TInt GetEMmcPartitionMapping(TInt aLocalPtn) const
+ {
+ __ASSERT_DEBUG((aLocalPtn >= 0) && (aLocalPtn < KMaxLocalDrives), Kern::Fault("Mmc: Array bounds exception", __LINE__));
+ return iEMmcPartitionMappings[aLocalPtn];
+ };
+
+
+private:
+ // MMC device specific stuff
+ TInt DoRead();
+ TInt DoWrite();
+ TInt DoFormat();
+ TInt Caps(TLocDrv& aDrive, TLocalDriveCapsV6& aInfo);
+
+ inline DMMCStack& Stack() const;
+ inline TInt CardNum() const;
+ inline TMediaRequest CurrentRequest() const;
+
+ TInt LaunchRead(TInt64 aStart, TUint32 aLength);
+ TInt LaunchDBRead();
+ TInt LaunchPhysRead(TInt64 aStart, TUint32 aLength);
+
+ TInt LaunchWrite(TInt64 aStart, TUint32 aLength, TMediaRequest aMedReq);
+ TInt LaunchFormat(TInt64 aStart, TUint32 aLength);
+
+ TInt LaunchRPIUnlock(TLocalDrivePasswordData& aData);
+ TInt LaunchRPIRead();
+ TInt LaunchRPIErase();
+ TInt DecodePartitionInfo();
+ TInt WritePartitionInfo();
+ TInt GetDefaultPartitionInfo(TMBRPartitionEntry& aPartitionEntry);
+ TInt CreateDefaultPartition();
+
+
+#if defined __TEST_PAGING_MEDIA_DRIVER__
+ TInt HandleControlIORequest();
+#endif
+
+ static void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
+
+ TInt CheckDevice(TMediaReqType aReqType);
+
+ static void SessionEndCallBack(TAny* aMediaDriver);
+ static void SessionEndDfc(TAny* aMediaDriver);
+ void DoSessionEndDfc();
+
+ static void DataTransferCallBack(TAny* aMediaDriver);
+ static void DataTransferCallBackDfc(TAny* aMediaDriver);
+
+ void DoReadDataTransferCallBack();
+ void DoWriteDataTransferCallBack();
+ void DoPhysReadDataTransferCallBack();
+ void DoPhysWriteDataTransferCallBack();
+
+ TInt AdjustPhysicalFragment(TPhysAddr &physAddr, TInt &physLength);
+ TInt PrepareFirstPhysicalFragment(TPhysAddr &aPhysAddr, TInt &aPhysLength, TUint32 aLength);
+ void PrepareNextPhysicalFragment();
+
+ TInt EngageAndSetReadRequest(TMediaRequest aRequest);
+ TInt EngageAndSetWriteRequest(TMediaRequest aRequest);
+ TInt EngageAndSetRequest(TMediaRequest aRequest, TInt aCurrent);
+ void CompleteRequest(TInt aReason);
+
+ TInt ReadDataUntilCacheExhausted(TBool* aAllDone);
+ TInt WriteDataToUser(TUint8* aBufPtr);
+ TInt ReadDataFromUser(TDes8& aDes, TInt aOffset);
+ TUint8* ReserveReadBlocks(TInt64 aStart, TInt64 aEnd, TUint32* aLength);
+ TUint8* ReserveWriteBlocks(TInt64 aMedStart, TInt64 aMedEnd, TUint* aRBM);
+ void MarkBlocks(TInt64 aStart, TInt64 aEnd, TInt aStartIndex);
+ void BuildGammaArray(TInt64 aStart, TInt64 aEnd);
+ void InvalidateCache();
+ void InvalidateCache(TInt64 aStart, TInt64 aEnd);
+ TUint8* IdxToCchMem(TInt aIdx) const;
+ TInt CchMemToIdx(TUint8* aMemP) const;
+
+ TInt DoPasswordOp();
+ void PasswordControl(TInt aFunc, TLocalDrivePasswordData& aData);
+ void Reset();
+ TInt AllocateSession();
+
+#ifdef _DEBUG_CACHE
+ TBool CacheInvariant();
+ TUint8* GetCachedBlock(TInt64 aAddr);
+#endif
+private:
+ DMMCStack* iStack; // controller objects
+ TMMCard* iCard;
+ DMMCSession* iSession;
+ DMMCSocket* iSocket;
+
+ TInt iCardNumber;
+
+ TUint iBlkLenLog2; // cached CSD data
+ TUint32 iBlkLen;
+ TInt64 iBlkMsk;
+ TBool iReadBlPartial;
+ TUint32 iPrWtGpLen; // preferred write group size in bytes,
+ TInt64 iPrWtGpMsk;
+
+ TInt iReadCurrentInMilliAmps; // power management
+ TInt iWriteCurrentInMilliAmps;
+
+ TUint8* iMinorBuf; // MBR, CMD42, partial read
+ TUint8* iCacheBuf; // cached buffer
+ TUint32 iMaxBufSize;
+ TInt iBlocksInBuffer;
+ TInt64* iCachedBlocks;
+ TInt* iGamma; // B lookup, ReserveReadBlocks()
+ TUint8* iIntBuf; // start of current buffer region
+ TInt iLstUsdCchEnt; // index of last used cache entry
+
+ TLocDrvRequest* iCurrentReq; // Current Request
+ TMediaRequest iMedReq;
+
+ TInt64 iReqStart; // user-requested start region
+ TInt64 iReqCur; // Currently requested start region
+ TInt64 iReqEnd; // user-requested end region
+ TInt64 iPhysStart; // physical region for one operation
+ TInt64 iPhysEnd; // physical end point for one operation
+ TInt64 iDbEnd; // Double buffer end point for one operation
+
+ TUint64 iEraseUnitMsk;
+
+ TUint iWtRBM; // Write - Read Before Modify Flags
+ TUint iRdROB; // Read - Read Odd Blocks Flags
+
+ TInt iFragOfset;
+ TUint32 iIPCLen;
+ TUint32 iNxtIPCLen;
+ TUint32 iBufOfset;
+
+ TUint iHiddenSectors; // bootup / password
+
+ TMMCCallBack iSessionEndCallBack;
+ TDfc iSessionEndDfc;
+
+ TPartitionInfo* iPartitionInfo;
+ TMMCMediaTypeEnum iMediaType;
+ TMMCEraseInfo iEraseInfo;
+ TBool iMbrMissing;
+ TInt iMediaId;
+
+ DMMCStack::TDemandPagingInfo iDemandPagingInfo;
+
+#if defined(__TEST_PAGING_MEDIA_DRIVER__)
+ SMmcStats iMmcStats;
+#endif // __TEST_PAGING_MEDIA_DRIVER__
+
+ TMMCCallBack iDataTransferCallBack; // Callback registered with the MMC stack to perform double-buffering
+ TDfc iDataTransferCallBackDfc; // ...and the associated DFC queue.
+
+ TBool iSecondBuffer; // Specified the currently active buffer
+ TBool iDoLastRMW; // ETrue if the last double-buffer transfer requires RMW modification
+ TBool iDoDoubleBuffer; // ETrue if double-buffering is currently active
+ TBool iDoPhysicalAddress; // ETrue if Physical Addressing is currently active
+ TBool iCreateMbr;
+ TBool iReadToEndOfCard; // {Read Only} ETrue if Reading to end of Card
+
+ TBool iInternalSlot;
+
+ DEMMCPartitionInfo* iMmcPartitionInfo; // Responsible for decoding partitions for embedded devices
+ TInt iEMmcPartitionMappings[KMaxLocalDrives]; // holds the mapping of emmc partitions
+ };
+
+#endif
+
--- a/kernel/eka/drivers/medmmc/medmmc.mmp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/medmmc.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -28,13 +28,20 @@
//Define this macro to create an MBR when formatting low-capacity MMC cards :
//macro SYMBIAN_CREATE_MBR_ON_LOW_CAPACITY_MMC
+// Define this macro to bypass automatic partition switching - in this case
+// switching can also be done by HandleControlIORequest()
+// macro EMMC_PARTITION_TEST_MODE_ENABLED
+
source medmmc.cpp
source mmcptn.cpp
+source medmmcpatchdata.cpp
library epbusmmc.lib
library elocd.lib
library emmcptn.lib
+DEFFILE ~/medmmc.def
+
linkas medmmc.pdd
start wins
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medmmc/medmmcpatchdata.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 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:
+// Media driver for MultiMediaCard Flash device, patchable constants
+//
+//
+
+#include <e32def.h>
+
+// Patchable constant used to enable TRIM. The feature is enabled by default.
+EXPORT_C extern const TUint KTRIMEnabled = 1;
--- a/kernel/eka/drivers/medmmc/mmcdp.h Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/medmmc/mmcdp.h Mon Oct 11 19:11:06 2010 +0100
@@ -21,7 +21,8 @@
#ifdef __TEST_PAGING_MEDIA_DRIVER__
-const TInt KMmcGetStats = 0x00000001;
+const TInt KMmcGetStats = 0x00000001;
+const TInt KMmcSwitchPartition = 0x00000002;
struct SMmcStats
{
TInt iReqPage;
--- a/kernel/eka/drivers/pbus/mmc/epbusm.mmh Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/epbusm.mmh Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 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"
@@ -37,6 +37,7 @@
source stackbody.cpp
source session.cpp
source mmccd_init.cpp
+source rpmbstack.cpp
library elocd.lib
@@ -48,4 +49,4 @@
uid 0x1000008d 0x10004087
-capability all
\ No newline at end of file
+capability all
--- a/kernel/eka/drivers/pbus/mmc/mmccd_init.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/mmccd_init.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -17,8 +17,7 @@
#include <drivers/mmccd_ifc.h>
#include <drivers/pbusmedia.h>
-
-
+#include <drivers/mmc.h>
/**
@@ -207,6 +206,10 @@
else
__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d not MMC card",i));
}
+
+ // set RpmbConfigRead to true and ensure that changes to RpmbConfigRead, NumberOfRpmbs
+ // and TheRpmbs are flushed at the same time
+ __e32_atomic_store_ord32(&RpmbParmsPopulated, ETrue);
__KTRACE_OPT(KPBUS1,Kern::Printf("<TMMCardControllerInterface::Create, ret %d",r));
return r;
@@ -230,8 +233,29 @@
if(pS == NULL)
return(KErrNoMemory);
- TMMCMachineInfo mi;
- pS->iStack->MachineInfo(mi);
+ // Retrieve RPMB specific information from the PSL layer
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Begin registering RPMB information from PSL layer"));
+
+ TMMCMachineInfoV44 mi;
+ TMMCMachineInfoV44Pckg machineInfoPckg(mi);
+ pS->iStack->MachineInfo(machineInfoPckg);
+
+ // Register each slot marked as being RPMB capable
+ // Code won't write beyond the end of TheRpmbs[] because 4 slots are reserved
+ // for each pbus socket and only 4 slots are processed for each socket
+ TInt rpmbSlots = (mi.iRpmbSlotCount <= 4) ? mi.iRpmbSlotCount : 4;
+
+ // if baseport set up so that iRpmbSlotList==NULL assert now
+ __ASSERT_ALWAYS((((rpmbSlots>0)&&(mi.iRpmbSlotList!=NULL))||(rpmbSlots==0)), Kern::Fault(__FILE__, __LINE__));
+ TInt i;
+ for ( i=0; i<rpmbSlots; i++)
+ {
+ TheRpmbs[NumberOfRpmbs].iSocketPtr = pS;
+ TheRpmbs[NumberOfRpmbs].iCardNumber = mi.iRpmbSlotList[i];
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: TheRpmbs[%d]: socketPtr %x: CardNumber %d", NumberOfRpmbs, pS, mi.iRpmbSlotList[i]));
+ NumberOfRpmbs++;
+ }
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Registering of RPMB information from PSL layer complete"));
// There may be more than one physical card slot for this socket/stack;
// if this is the case, then we have to create a separate DPBusPrimaryMedia
@@ -258,7 +282,7 @@
#endif // __WINS__
- for (TInt i=0; i<physicalCardSlots ; i++)
+ for (i=0; i<physicalCardSlots ; i++)
{
DPBusPrimaryMedia* pMedia = new DPBusPrimaryMedia(pS);
if (pMedia == NULL)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/pbus/mmc/rpmbstack.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,356 @@
+// Copyright (c) 2010 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:
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include <drivers/mmc.h>
+#include <drivers/rpmbpacket.h>
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "../../../include/drivers/locmedia_ost.h"
+#ifdef __VC32__
+#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
+#endif
+#include "rpmbstackTraces.h"
+#endif
+
+TMMCErr DMMCStack::CIMRpmbAccessSM()
+ {
+enum TStates
+ {
+ EStBegin,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+
+ //Extract the RPMB request type from the command. JEDEC specify this to be situated
+ //at offset 0 in the packet. When accessing the hardware, this is reversed and is
+ //at offset 511
+ TUint8 requestType = * (s.Command().iDataMemoryP + KRpmbRequestLsbOffset);
+
+ //There are 5 possible rpmb request types that can be passed through the state machines:
+ //
+ //Authentication Key programming request: KRpmbRequestWriteKey = 0x001
+ //Reading of the write counter value request: KRpmbRequestReadWriteCounter = 0x0002;
+ //Authenticated data write request: KRpmbRequestWriteData = 0x0003;
+ //Authenticated data read request: KRpmbRequestReadData = 0x0004;
+ //Result read request: KRpmbRequestReadResultRegister = 0x0005;
+ //
+
+ SMF_BEGIN
+
+ switch (requestType)
+ {
+ case KRpmbRequestWriteKey:
+ SMF_INVOKES(CIMRpmbWriteAuthenticationKeySMST, EStEnd);
+ case KRpmbRequestReadWriteCounter:
+ SMF_INVOKES(CIMRpmbReadWrCounterSMST, EStEnd);
+ case KRpmbRequestWriteData:
+ SMF_INVOKES(CIMRpmbWriteSMST, EStEnd);
+ case KRpmbRequestReadData:
+ SMF_INVOKES(CIMRpmbReadSMST, EStEnd);
+ default:
+ break;
+ }
+
+ SMF_END
+}
+
+
+TMMCErr DMMCStack::CIMRpmbWriteAuthenticationKeySM()
+ {
+ enum TStates
+ {
+ EStBegin, // Write key request
+ EStSetupReadRequest,
+ EStReadResult,
+ EStError,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+
+ SMF_BEGIN
+
+ //
+ // Setup write request
+ // CMD23 Reliable Write = 1 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendRequest(ETrue);
+ //
+ // KMMCErrByPass is routinely thrown in the ReadWriteBlocks state machine.
+ // It is thrown to indicate that the current command in the state machine is not CMD42(lock/unlock)
+ // We need to trap this error here to stop the RPMB state machines from unravelling and passing
+ // the error upwards.
+ //
+ m.SetTraps(KMMCErrBypass);
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM1, "RPMB: Write Key State Machine - send write key request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - send write key request packet"));
+
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStSetupReadRequest);
+
+ SMF_STATE(EStSetupReadRequest)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM2, "RPMB: Write Key State Machine - sent write key request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent write key request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM3, "RPMB: Write Key State Machine - sent write key request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent write key request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read result register request
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendReadResultRegisterRequest();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM4, "RPMB: Write Key State Machine - send read result register request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - send read result register request packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+ SMF_STATE(EStReadResult)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM5, "RPMB: Write Key State Machine - sent read result register request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent read result register request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM6, "RPMB: Write Key State Machine - sent read result register request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - sent read result register request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read response
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD18
+ //
+ s.SetupRpmbReceiveResponse();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITEAUTHENTICATIONKEYSM7, "RPMB: Write Key State Machine - get read packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write Key State Machine - get read packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+ SMF_STATE(EStError)
+ SMF_RETURN(err);
+
+ SMF_END
+ }
+
+
+TMMCErr DMMCStack::CIMRpmbReadWrCounterSM()
+ {
+ enum TStates
+ {
+ EStBegin, // Read counter request
+ EStReadResult,
+ EStError,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+
+ SMF_BEGIN
+
+ //
+ // Setup write request
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendRequest(EFalse);
+ m.SetTraps(KMMCErrBypass);
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM1, "RPMB: Read Write Counter State Machine - send read counter request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - send read counter request packet"));
+
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+ SMF_STATE(EStReadResult)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM2, "RPMB: Read Write Counter State Machine - sent read counter request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - sent read counter request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM3, "RPMB: Read Write Counter State Machine - sent read counter request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - sent read counter request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read response
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD18
+ //
+ s.SetupRpmbReceiveResponse();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADWRCOUNTERSM4, "RPMB: Read Write Counter State Machine - get read packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read Write Counter State Machine - get read packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+ SMF_STATE(EStError)
+ SMF_RETURN(err);
+
+ SMF_END
+ }
+
+
+TMMCErr DMMCStack::CIMRpmbWriteSM()
+ {
+ enum TStates
+ {
+ EStBegin, // Write data request
+ EStSetupReadRequest,
+ EStReadResult,
+ EStError,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+
+ SMF_BEGIN
+
+ //
+ // Setup write request
+ // CMD23 Reliable Write = 1 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendRequest(ETrue);
+ m.SetTraps(KMMCErrBypass);
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM1, "RPMB: Write State Machine - send write request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - send write request packet"));
+
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStSetupReadRequest);
+
+ SMF_STATE(EStSetupReadRequest)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM2, "RPMB: Write State Machine - sent write request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent write request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM3, "RPMB: Write State Machine - sent write request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent write request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read result register request
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendReadResultRegisterRequest();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM4, "RPMB: Write State Machine - send read result register request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - send read result register request packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+ SMF_STATE(EStReadResult)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM5, "RPMB: Write State Machine - sent read result register request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent read result register request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM6, "RPMB: Write State Machine - sent read result register request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - sent read result register request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read response
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD18
+ //
+ s.SetupRpmbReceiveResponse();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBWRITESM7, "RPMB: Write State Machine - get read packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Write State Machine - get read packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+ SMF_STATE(EStError)
+ SMF_RETURN(err);
+
+ SMF_END
+ }
+
+
+TMMCErr DMMCStack::CIMRpmbReadSM()
+ {
+ enum TStates
+ {
+ EStBegin, // Read data request
+ EStReadResult,
+ EStError,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+
+ SMF_BEGIN
+
+ //
+ // Setup write request
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD25
+ //
+ s.SetupRpmbSendRequest(EFalse);
+ m.SetTraps(KMMCErrBypass);
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM1, "RPMB: Read State Machine - send read request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - send read request packet"));
+
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStReadResult)
+
+ SMF_STATE(EStReadResult)
+
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM2, "RPMB: Read State Machine - sent read request packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - sent read request packet"));
+
+ if (err != KMMCErrNone)
+ {
+ OstTrace1(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM3, "RPMB: Read State Machine - sent read request packet error = %d", err);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - sent read request packet error = %d", err));
+ SMF_GOTOS(EStError);
+ }
+ //
+ // Setup read response
+ // CMD23 Reliable Write = 0 Block Count = 1
+ // CMD18
+ //
+ s.SetupRpmbReceiveResponse();
+ OstTrace0(TRACE_FLOW, DMMCSTACK_CIMRPMBREADSM4, "RPMB: Read State Machine - get read packet");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: Read State Machine - get read packet"));
+ SMF_INVOKES(CIMReadWriteBlocksSMST, EStEnd);
+
+ SMF_STATE(EStError)
+ SMF_RETURN(err);
+
+ SMF_END
+ }
+
+TMMCErr DMMCStack::CIMRpmbAccessSMST(TAny* aStackP)
+ {return(static_cast<DMMCStack*>(aStackP)->CIMRpmbAccessSM());}
+TMMCErr DMMCStack::CIMRpmbWriteAuthenticationKeySMST(TAny* aStackP)
+ {return(static_cast<DMMCStack*>(aStackP)->CIMRpmbWriteAuthenticationKeySM());}
+TMMCErr DMMCStack::CIMRpmbReadWrCounterSMST(TAny* aStackP)
+ {return(static_cast<DMMCStack*>(aStackP)->CIMRpmbReadWrCounterSM());}
+TMMCErr DMMCStack::CIMRpmbWriteSMST(TAny* aStackP)
+ {return(static_cast<DMMCStack*>(aStackP)->CIMRpmbWriteSM());}
+TMMCErr DMMCStack::CIMRpmbReadSMST(TAny* aStackP)
+ {return(static_cast<DMMCStack*>(aStackP)->CIMRpmbReadSM());}
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
- Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+ MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/sdio/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bmarm/sdcard3c/sdio/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
InitStackAfterUnlockSM__9DMMCStack @ 94 NONAME ; DMMCStack::InitStackAfterUnlockSM(void)
RegisterMediaDevices__26TMMCardControllerInterfacei @ 95 NONAME ; TMMCardControllerInterface::RegisterMediaDevices(int)
ModifyCardCapabilitySM__9DMMCStack @ 96 NONAME R3UNUSED ; DMMCStack::ModifyCardCapabilitySM(void)
- Dummy1__9DMMCStack @ 97 NONAME R3UNUSED ; DMMCStack::Dummy1(void)
+ MMCGetExtInterface__F18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 97 NONAME
GetInterface__9DMMCStackQ29DMMCStack12TInterfaceIdRPQ29DMMCStack10MInterface @ 98 NONAME R3UNUSED ; DMMCStack::GetInterface(DMMCStack::TInterfaceId, DMMCStack::MInterface *&)
MachineInfo__9DMMCStackR5TDes8 @ 99 NONAME R3UNUSED ; DMMCStack::MachineInfo(TDes8 &)
SetBusWidth__9DMMCStackUl @ 100 NONAME R3UNUSED ; DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/sdio/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bwins/sdcard3c/sdio/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?InitStackAfterUnlockSM@DMMCStack@@MAEKXZ @ 94 NONAME ; protected: virtual unsigned long __thiscall DMMCStack::InitStackAfterUnlockSM(void)
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 95 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?ModifyCardCapabilitySM@DMMCStack@@MAEKXZ @ 96 NONAME ; unsigned long DMMCStack::ModifyCardCapabilitySM(void)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; void DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME ; int MMCGetExtInterface(enum TMMCExtInterfaceId, class MMCMExtInterface * &, void *)
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/sdio/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/bx86/sdcard3c/sdio/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -95,7 +95,7 @@
?RegisterMediaDevices@TMMCardControllerInterface@@MAEHH@Z @ 94 NONAME ; protected: virtual int __thiscall TMMCardControllerInterface::RegisterMediaDevices(int)
?RequestAsyncPowerDown@DPBusSocket@@QAEXXZ @ 95 NONAME ; public: void __thiscall DPBusSocket::RequestAsyncPowerDown(void)
?ControlIO@DPBusSocket@@UAEHHPAX0@Z @ 96 NONAME ; public: virtual int __thiscall DPBusSocket::ControlIO(int,void *,void *)
- ?Dummy1@DMMCStack@@EAEXXZ @ 97 NONAME ; private: virtual void __thiscall DMMCStack::Dummy1(void)
+ ?MMCGetExtInterface@@YAHW4TMMCExtInterfaceId@@AAPAVMMCMExtInterface@@PAX@Z @ 97 NONAME
?GetInterface@DMMCStack@@MAEXW4TInterfaceId@1@AAPAVMInterface@1@@Z @ 98 NONAME ; protected: virtual void __thiscall DMMCStack::GetInterface(enum DMMCStack::TInterfaceId,class DMMCStack::MInterface * &)
?MachineInfo@DMMCStack@@UAEXAAVTDes8@@@Z @ 99 NONAME ; public: virtual void __thiscall DMMCStack::MachineInfo(class TDes8 &)
?SetBusWidth@DMMCStack@@MAEXK@Z @ 100 NONAME ; protected: virtual void __thiscall DMMCStack::SetBusWidth(unsigned long)
--- a/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
- _ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+ _Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- a/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/eabi/sdcard3c/sdio/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
- _ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+ _Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- a/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/sdcard/sdcard3c/sdcard.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -1482,8 +1482,8 @@
SMF_STATE(EstCheckController)
OstTrace0( TRACE_INTERNALS, DSDSTACK_SWITCHTOHIGHSPEEDMODESM2, "EstCheckController");
// Get the clock speed supported by the controller
- TMMCMachineInfoV4 machineInfo;
- TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
+ TMMCMachineInfoV44 machineInfo;
+ TMMCMachineInfoV44Pckg machineInfoPckg(machineInfo);
MachineInfo(machineInfoPckg);
if (machineInfo.iVersion >= TMMCMachineInfoV4::EVersion4)
--- a/kernel/eka/drivers/pbus/mmc/session.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/session.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -36,6 +36,7 @@
* @param aCallBack reference to a TMMCCallback object to be called upon completion.
*/
: iCallBack(aCallBack),
+ iPartition(TExtendedCSD::ESelectUserArea), // UDA is the hardware default
#ifdef __EPOC32__
iPollTimer(DMMCSession::PollTimerCallBack, this),
iRetryTimer(DMMCSession::RetryTimerCallBack, this),
@@ -419,7 +420,8 @@
DMMCStack::NoSessionSMST, // CIMLockStack is never really executed as a session
DMMCStack::InitStackAfterUnlockSMST,
DMMCStack::CIMAutoUnlockSMST,
- DMMCStack::ExecSleepCommandSMST // CIMSleep
+ DMMCStack::ExecSleepCommandSMST, // CIMSleep
+ DMMCStack::CIMRpmbAccessSMST // CIMRpmbAccess
};
if (aSessNum >= 0 && aSessNum < (TInt) KMMCMaxSessionTypeNumber)
--- a/kernel/eka/drivers/pbus/mmc/stack.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/drivers/pbus/mmc/stack.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -20,6 +20,23 @@
#include <drivers/locmedia.h>
#include "stackbody.h"
+/*
+ Global helper object shared by all stacks to hold device specific RPMB information
+ */
+ static MRpmbInfo rpmbInfo;
+
+/*
+ Global counter for number or RPMB partitions. Only one partition per device
+*/
+
+GLDEF_D TUint NumberOfRpmbs = 0;
+/*
+ Global holder for RPMB parameters
+ */
+GLDEF_D TRpmbDeviceParms TheRpmbs[KMaxPBusSockets*4];
+
+GLDEF_D TBool RpmbParmsPopulated = EFalse;
+
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "../../../include/drivers/locmedia_ost.h"
@@ -3007,6 +3024,79 @@
}
+TMMCErr DMMCStack::SwitchPartitionSM()
+/**
+ * This SM function must be invoked before execution of any partition-specific command.
+ *
+ * @return MMC error code
+ */
+ {
+ __KTRACE_OPT(KPBUS1,Kern::Printf("=mst:sp"));
+
+ enum states
+ {
+ EStBegin=0,
+ EStPartitionSelected,
+ EStEnd
+ };
+
+ DMMCSession& s=Session();
+ OstTrace1( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM1, "Current session=0x%x", &s );
+
+ SMF_BEGIN
+
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM2, "EStBegin" );
+
+ TMMCard *cardP = s.CardP();
+ if(cardP)
+ {
+ TInt curPtn = cardP->ExtendedCSD().BootConfig() & KMMCSelectPartitionMask;
+ TInt tgtPtn = s.Partition() & KMMCSelectPartitionMask;
+
+ if(curPtn != tgtPtn)
+ {
+ OstTraceExt2( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM3,
+ "EStSelectPartition: Switching partitions from 0x%02X to 0x%02X",
+ (TUint32) curPtn, (TUint32) tgtPtn);
+
+ // need to preserve the non-partition related bits
+ tgtPtn |= cardP->ExtendedCSD().BootConfig() & ~KMMCSelectPartitionMask;
+
+ TMMCArgument arg = TExtendedCSD::GetWriteArg(
+ TExtendedCSD::EWriteByte, TExtendedCSD::EBootConfigIndex, tgtPtn, 0);
+
+ CurrentSessPushCmdStack();
+ s.FillCommandDesc(ECmdSwitch, arg);
+ SMF_INVOKES(ExecSwitchCommandST, EStPartitionSelected)
+ }
+ }
+
+ // no switching required
+ SMF_GOTOS( EStEnd )
+
+ SMF_STATE(EStPartitionSelected)
+
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM4, "EStPartitionSelected" );
+ const TMMCStatus status(s.ResponseP());
+ CurrentSessPopCmdStack();
+ if (status.Error())
+ {
+ OstTraceFunctionExitExt( DMMCSTACK_SWITCHPARTITIONSM_EXIT1, this, (TInt) KMMCErrStatus );
+ return KMMCErrStatus;
+ }
+ else
+ { // update extended CSD
+ TInt ptn = (s.CardP()->ExtendedCSD().BootConfig() & ~KMMCSelectPartitionMask) | (s.Partition() & KMMCSelectPartitionMask);
+ memset( s.CardP()->iExtendedCSD.Ptr() + TExtendedCSD::EBootConfigIndex, ptn, 1);
+ OstTrace1( TRACE_INTERNALS, DMMCSTACK_SWITCHPARTITIONSM5,
+ "EStPartitionSelected: Switched to partition 0x%02X", ptn );
+ }
+
+ SMF_END
+
+ }
+
+
inline TMMCErr DMMCStack::AttachCardSM()
/**
* This SM function must be invoked by every session which is CardControlled.
@@ -3045,7 +3135,6 @@
s.SynchBlock( KMMCBlockOnCardInUse );
SMF_WAIT
}
-
if( s.iCardP->IsPresent() && s.iCardP->iCID == s.iCID )
s.iCardP->iUsingSessionP = &s;
else
@@ -3070,6 +3159,7 @@
SMF_STATE(EStAttStatus)
+
OstTrace0( TRACE_INTERNALS, DMMCSTACK_ATTACHCARDSM3, "EStAttStatus" );
CurrentSessPopCmdStack();
OstTraceFunctionExitExt( DMMCSTACK_ATTACHCARDSM_EXIT3, this, (TInt) err );
@@ -3357,53 +3447,101 @@
SMF_GOTOS(EStExit);
}
+
+
memcpy(s.CardP()->iExtendedCSD.Ptr(), iPSLBuf, KMMCExtendedCSDLength);
+
+
// Call a licencee-specific state machine to allow the Extended CSD register to be modified.
SMF_INVOKES( ModifyCardCapabilitySMST, EStGotModifiedExtendedCSD )
SMF_STATE(EStGotModifiedExtendedCSD)
OstTrace0( TRACE_INTERNALS, DMMCSTACK_INITSTACKAFTERUNLOCKSM7, "EStGotExtendedCSD" );
+
+ const TExtendedCSD& extendedCSD = s.CardP()->ExtendedCSD();
__KTRACE_OPT(KPBUS1, Kern::Printf("Extended CSD"));
- __KTRACE_OPT(KPBUS1, Kern::Printf("CSDStructureVer: %u", s.CardP()->ExtendedCSD().CSDStructureVer()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("ExtendedCSDRev: %u", s.CardP()->ExtendedCSD().ExtendedCSDRev()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("CSDStructureVer: %u", extendedCSD.CSDStructureVer()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("ExtendedCSDRev: %u", extendedCSD.ExtendedCSDRev()));
__KTRACE_OPT(KPBUS1, Kern::Printf("-------------------------------"));
- __KTRACE_OPT(KPBUS1, Kern::Printf("SupportedCmdSet: %u", s.CardP()->ExtendedCSD().SupportedCmdSet()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz360V: 0x%02X", s.CardP()->ExtendedCSD().PowerClass26Mhz360V()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz360V: 0x%02X", s.CardP()->ExtendedCSD().PowerClass52Mhz360V()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz195V: 0x%02X", s.CardP()->ExtendedCSD().PowerClass26Mhz195V()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz195V: 0x%02X", s.CardP()->ExtendedCSD().PowerClass52Mhz195V()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("CardType: %u", s.CardP()->ExtendedCSD().CardType()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("CmdSet: %u", s.CardP()->ExtendedCSD().CmdSet()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("CmdSetRev: %u", s.CardP()->ExtendedCSD().CmdSetRev()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass: %u", s.CardP()->ExtendedCSD().PowerClass()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("HighSpeedTiming: %u", s.CardP()->ExtendedCSD().HighSpeedTiming()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("HighCapacityEraseGroupSize: %u", s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("AccessSize: %u", s.CardP()->ExtendedCSD().AccessSize()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("BootInfo: %u", s.CardP()->ExtendedCSD().BootInfo() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("BootSizeMultiple: %u", s.CardP()->ExtendedCSD().BootSizeMultiple() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("EraseTimeoutMultiple: %u", s.CardP()->ExtendedCSD().EraseTimeoutMultiple() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("ReliableWriteSector: %u", s.CardP()->ExtendedCSD().ReliableWriteSector() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("HighCapWriteProtGroupSize: %u", s.CardP()->ExtendedCSD().HighCapacityWriteProtectGroupSize() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVcc: %u", s.CardP()->ExtendedCSD().SleepCurrentVcc() ));
- __KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVccQ: %u", s.CardP()->ExtendedCSD().SleepCurrentVccQ()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("SleepAwakeTimeout: %u", s.CardP()->ExtendedCSD().SleepAwakeTimeout()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("BootConfig: %u", s.CardP()->ExtendedCSD().BootConfig()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("BootBusWidth: %u", s.CardP()->ExtendedCSD().BootBusWidth()));
- __KTRACE_OPT(KPBUS1, Kern::Printf("EraseGroupDef: %u", s.CardP()->ExtendedCSD().EraseGroupDef()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("SupportedCmdSet: %u", extendedCSD.SupportedCmdSet()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz360V: 0x%02X", extendedCSD.PowerClass26Mhz360V()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz360V: 0x%02X", extendedCSD.PowerClass52Mhz360V()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass26Mhz195V: 0x%02X", extendedCSD.PowerClass26Mhz195V()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass52Mhz195V: 0x%02X", extendedCSD.PowerClass52Mhz195V()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("CardType: %u", extendedCSD.CardType()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("CmdSet: %u", extendedCSD.CmdSet()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("CmdSetRev: %u", extendedCSD.CmdSetRev()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PowerClass: %u", extendedCSD.PowerClass()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("HighSpeedTiming: %u", extendedCSD.HighSpeedTiming()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("HighCapacityEraseGroupSize: %u", extendedCSD.HighCapacityEraseGroupSize()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("AccessSize: %u", extendedCSD.AccessSize()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootInfo: %u", extendedCSD.BootInfo() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootSizeMultiple: %u", extendedCSD.BootSizeMultiple() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("EraseTimeoutMultiple: %u", extendedCSD.EraseTimeoutMultiple() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("ReliableWriteSector: %u", extendedCSD.ReliableWriteSector() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("HighCapWriteProtGroupSize: %u", extendedCSD.HighCapacityWriteProtectGroupSize() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVcc: %u", extendedCSD.SleepCurrentVcc() ));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("SleepCurrentVccQ: %u", extendedCSD.SleepCurrentVccQ()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("SleepAwakeTimeout: %u", extendedCSD.SleepAwakeTimeout()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootConfig: %u", extendedCSD.BootConfig()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootBusWidth: %u", extendedCSD.BootBusWidth()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("EraseGroupDef: %u", extendedCSD.EraseGroupDef()));
+
+ // 4.4 extensions
+ __KTRACE_OPT(KPBUS1, Kern::Printf("ErasedMemoryContent: 0x%02X", extendedCSD.ErasedMemoryContent()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootConfigProtection: 0x%02X", extendedCSD.BootConfigProt()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BootAreaWriteProtectionReg: 0x%02X", extendedCSD.BootAreaWriteProtectionReg()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("UserAreaWriteProtectionReg: 0x%02X", extendedCSD.UserAreaWriteProtectionReg()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("FWConfiguration: 0x%02X", extendedCSD.FwConfiguration()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMBSize: 0x%04X", extendedCSD.RpmbSize()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("HwResetFunction: 0x%02X", extendedCSD.HwResetFunction()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PartitioningSupport: 0x%02X", extendedCSD.PartitioningSupport()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("MaxEnhancedAreaSize: 0x%04X", extendedCSD.MaxEnhancedAreaSize()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PartitionsAttribute: 0x%02X", extendedCSD.PartitionsAttribute()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("PartitioningSetting: 0x%02X", extendedCSD.PartitioningSetting()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("GPP1: 0x%04X", extendedCSD.GeneralPurposePartition1Size()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("GPP2: 0x%04X", extendedCSD.GeneralPurposePartition2Size()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("GPP3: 0x%04X", extendedCSD.GeneralPurposePartition3Size()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("GPP4: 0x%04X", extendedCSD.GeneralPurposePartition4Size()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("EnhancedUserDataSize: 0x%04X", extendedCSD.EnhancedUserDataAreaSize()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("EnhancedUserDataStartAddr: 0x%04X", extendedCSD.EnhancedUserDataStartAddress()));
+ __KTRACE_OPT(KPBUS1, Kern::Printf("BadBlockManagementMode: 0x%04X", extendedCSD.BadBlockManagementMode()));
+
+
+ OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM8, "CSDStructureVer=%u; ExtendedCSDRev=%u; SupportedCmdSet=%u", extendedCSD.CSDStructureVer(), extendedCSD.ExtendedCSDRev(), extendedCSD.SupportedCmdSet() );
+ OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM9, "PowerClass26Mhz360V=0x%02x; PowerClass52Mhz360V=0x%02x; PowerClass26Mhz195V=0x%02x; PowerClass52Mhz195V=0x%02x", extendedCSD.PowerClass26Mhz360V(), extendedCSD.PowerClass52Mhz360V(), extendedCSD.PowerClass26Mhz195V(), extendedCSD.PowerClass52Mhz195V() );
+ OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM10, "CardType=%u; CmdSet=%u; CmdSetRev=%u; PowerClass=%u; HighSpeedTiming=%u", extendedCSD.CardType(), extendedCSD.CmdSet(), extendedCSD.CmdSetRev(), extendedCSD.PowerClass(), extendedCSD.HighSpeedTiming() );
+ OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM11, "HighCapacityEraseGroupSize=%u; AccessSize=%u; BootInfo=%u; BootSizeMultiple=%u; EraseTimeoutMultiple=%u", extendedCSD.HighCapacityEraseGroupSize(), extendedCSD.AccessSize(), extendedCSD.BootInfo(), extendedCSD.BootSizeMultiple(), extendedCSD.EraseTimeoutMultiple() );
+ OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM12, "ReliableWriteSector=%u; HighCapWriteProtGroupSize=%u; SleepCurrentVcc=%u; SleepCurrentVccQ=%u; SleepAwakeTimeout=%u", extendedCSD.ReliableWriteSector(), extendedCSD.HighCapacityWriteProtectGroupSize(), extendedCSD.SleepCurrentVcc(), extendedCSD.SleepCurrentVccQ(), extendedCSD.SleepAwakeTimeout() );
+ OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM13, "BootConfig=%u; BootBusWidth=%u; EraseGroupDef=%u", extendedCSD.BootConfig(), extendedCSD.BootBusWidth(), extendedCSD.EraseGroupDef() );
+
+ // 4.4 extensions
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx1, "ErasedMemoryContent: 0x%02X", extendedCSD.ErasedMemoryContent());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx2, "BootConfigProtection: 0x%02X", extendedCSD.BootConfigProt());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx3, "BootAreaWriteProtectionReg: 0x%02X", extendedCSD.BootAreaWriteProtectionReg());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx4, "UserAreaWriteProtectionReg: 0x%02X", extendedCSD.UserAreaWriteProtectionReg());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx5, "FWConfiguration: 0x%02X", extendedCSD.FwConfiguration());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx6, "RPMBSize: 0x%04X", extendedCSD.RpmbSize());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx7, "HwResetFunction: 0x%02X", extendedCSD.HwResetFunction());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx8, "PartitioningSupport: 0x%02X", extendedCSD.PartitioningSupport());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx9, "MaxEnhancedAreaSize: 0x%04X", extendedCSD.MaxEnhancedAreaSize());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx10, "PartitionsAttribute: 0x%02X", extendedCSD.PartitionsAttribute());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx11, "PartitioningSetting: 0x%02X", extendedCSD.PartitioningSetting());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx12, "GPP1: 0x%04X", extendedCSD.GeneralPurposePartition1Size());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx13, "GPP2: 0x%04X", extendedCSD.GeneralPurposePartition2Size());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx14, "GPP3: 0x%04X", extendedCSD.GeneralPurposePartition3Size());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx15, "GPP4: 0x%04X", extendedCSD.GeneralPurposePartition4Size());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx16, "EnhancedUserDataSize: 0x%04X", extendedCSD.EnhancedUserDataAreaSize());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx17, "EnhancedUserDataStartAddr: 0x%04X", extendedCSD.EnhancedUserDataStartAddress());
+ OstTraceDef1( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSMx18, "BadBlockManagementMode: 0x%04X", extendedCSD.BadBlockManagementMode());
+
- OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM8, "CSDStructureVer=%u; ExtendedCSDRev=%u; SupportedCmdSet=%u", s.CardP()->ExtendedCSD().CSDStructureVer(), s.CardP()->ExtendedCSD().ExtendedCSDRev(), s.CardP()->ExtendedCSD().SupportedCmdSet() );
- OstTraceDefExt4( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM9, "PowerClass26Mhz360V=0x%02x; PowerClass52Mhz360V=0x%02x; PowerClass26Mhz195V=0x%02x; PowerClass52Mhz195V=0x%02x", s.CardP()->ExtendedCSD().PowerClass26Mhz360V(), s.CardP()->ExtendedCSD().PowerClass52Mhz360V(), s.CardP()->ExtendedCSD().PowerClass26Mhz195V(), s.CardP()->ExtendedCSD().PowerClass52Mhz195V() );
- OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM10, "CardType=%u; CmdSet=%u; CmdSetRev=%u; PowerClass=%u; HighSpeedTiming=%u", s.CardP()->ExtendedCSD().CardType(), s.CardP()->ExtendedCSD().CmdSet(), s.CardP()->ExtendedCSD().CmdSetRev(), s.CardP()->ExtendedCSD().PowerClass(), s.CardP()->ExtendedCSD().HighSpeedTiming() );
- OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM11, "HighCapacityEraseGroupSize=%u; AccessSize=%u; BootInfo=%u; BootSizeMultiple=%u; EraseTimeoutMultiple=%u", s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize(), s.CardP()->ExtendedCSD().AccessSize(), s.CardP()->ExtendedCSD().BootInfo(), s.CardP()->ExtendedCSD().BootSizeMultiple(), s.CardP()->ExtendedCSD().EraseTimeoutMultiple() );
- OstTraceDefExt5( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM12, "ReliableWriteSector=%u; HighCapWriteProtGroupSize=%u; SleepCurrentVcc=%u; SleepCurrentVccQ=%u; SleepAwakeTimeout=%u", s.CardP()->ExtendedCSD().ReliableWriteSector(), s.CardP()->ExtendedCSD().HighCapacityWriteProtectGroupSize(), s.CardP()->ExtendedCSD().SleepCurrentVcc(), s.CardP()->ExtendedCSD().SleepCurrentVccQ(), s.CardP()->ExtendedCSD().SleepAwakeTimeout() );
- OstTraceDefExt3( OST_TRACE_CATEGORY_RND, TRACE_MMCDEBUG, DMMCSTACK_INITSTACKAFTERUNLOCKSM13, "BootConfig=%u; BootBusWidth=%u; EraseGroupDef=%u", s.CardP()->ExtendedCSD().BootConfig(), s.CardP()->ExtendedCSD().BootBusWidth(), s.CardP()->ExtendedCSD().EraseGroupDef() );
-
- if (s.CardP()->ExtendedCSD().ExtendedCSDRev() >= 3)
- {
- if (!(s.CardP()->ExtendedCSD().EraseGroupDef()) && s.CardP()->ExtendedCSD().HighCapacityEraseGroupSize())
+ if (extendedCSD.ExtendedCSDRev() >= 3)
+ {
+ if (!(extendedCSD.EraseGroupDef()) && extendedCSD.HighCapacityEraseGroupSize())
{
// Need to ensure that media is using correct erase group sizes.
TMMCArgument arg = TExtendedCSD::GetWriteArg(
@@ -3429,7 +3567,7 @@
if (err == KMMCErrNone)
{
- // EEraseGroupDef has been updated succussfully,
+ // EEraseGroupDef has been updated successfully,
// update the Extended CSD to reflect this
memset( s.CardP()->iExtendedCSD.Ptr()+TExtendedCSD::EEraseGroupDefIndex, TExtendedCSD::EEraseGrpDefEnableHighCapSizes, 1);
}
@@ -3948,8 +4086,8 @@
// Get the bus widths & clocks supported by the controller
// NB If the PSL doesn not support TMMCMachineInfoV4, return
- TMMCMachineInfoV4 machineInfo;
- TMMCMachineInfoV4Pckg machineInfoPckg(machineInfo);
+ TMMCMachineInfoV44 machineInfo;
+ TMMCMachineInfoV44Pckg machineInfoPckg(machineInfo);
MachineInfo(machineInfoPckg);
if (machineInfo.iVersion < TMMCMachineInfoV4::EVersion4)
{
@@ -5724,6 +5862,7 @@
EStBegin=0,
EStRestart,
EStAttached,
+ EStLength,
EStLength1,
EStLengthSet,
EStIssueBlockCount,
@@ -5755,7 +5894,6 @@
return KMMCErrNotSupported;
}
}
-
s.iState |= KMMCSessStateInProgress;
m.SetTraps(KMMCErrInitContext);
@@ -5770,9 +5908,15 @@
SMF_INVOKES( AttachCardSMST, EStAttached ) // attachment is mandatory here
}
+
SMF_BPOINT(EStAttached)
OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM4, "EStAttached" );
+ SMF_INVOKES( SwitchPartitionSMST, EStLength ) // may have to switch partitions
+
+ SMF_STATE(EStLength)
+
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM16, "EStLength" );
TMMCCommandDesc& cmd = s.Command();
const TUint32 blockLength = cmd.BlockLength();
@@ -5809,7 +5953,7 @@
SMF_STATE(EStLength1)
- OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM5, "EStAttached" );
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM5, "EStLength" );
const TMMCStatus status(s.ResponseP());
CurrentSessPopCmdStack();
if (status.Error())
@@ -5851,17 +5995,19 @@
const TUint blocks = cmd.NumBlocks();
- SMF_NEXTS(EStBpoint1)
+ SMF_NEXTS(EStBpoint1)
+
if ( !(opType & kTypeSpecial) ) // A special session has already set its command descriptor
{
+
if (cmd.iFlags & KMMCCmdFlagReliableWrite)
//ensure multiple block commands are used for reliable writing
opType |= kTypeMultiple;
- if ( (blocks==1) && !(cmd.iFlags & KMMCCmdFlagReliableWrite) )
+ if ( (blocks==1) && !(cmd.iFlags & KMMCCmdFlagReliableWrite) && !(cmd.iFlags & KMMCCmdFlagRpmbIO))
{
- // Reliable Write requires that Multi-Block command is used.
+ // Reliable Write & RPMB require that Multi-Block command is used.
opType &= ~kTypeMultiple;
}
@@ -6005,7 +6151,7 @@
// Fall through if CURRENT_STATE is not PGM or DATA
SMF_STATE(EStRWFinish)
- OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM15, "EStRWFinish" );
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMREADWRITEBLOCKSSM15, "EStRWFinish" );
if (TMMCStatus(s.ResponseP()).Error() != 0)
{
OstTraceFunctionExitExt( DMMCSTACK_CIMREADWRITEBLOCKSSM_EXIT8, this, (TInt) KMMCErrStatus );
@@ -6034,6 +6180,7 @@
EStBegin=0,
EStRestart,
EStAttached,
+ EStLength,
EStStartTagged,
EStEndTagged,
EStErased,
@@ -6069,13 +6216,21 @@
OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM3, "EStRestart" );
SMF_CALLMEWR(EStRestart) // Create a recursive call entry to recover from Init
-
- s.ResetCommandStack();
+
+ CurrentSessPushCmdStack(); //Push stack pointer to preserve flags for TRIM
+
SMF_INVOKES( AttachCardSMST, EStAttached ) // attachment is mandatory
SMF_BPOINT(EStAttached)
OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM4, "EStAttached" );
+ SMF_INVOKES( SwitchPartitionSMST, EStLength ) // may have to switch partitions
+
+ SMF_STATE(EStLength)
+
+ OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM13, "EStLength" );
+
+ CurrentSessPopCmdStack();
TMMCCommandDesc& cmd = s.Command();
if(cmd.iTotalLength == 0)
@@ -6095,6 +6250,14 @@
break;
case ECIMEraseGroup:
OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM6, "ECIMEraseGroup" );
+
+ if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+ {
+ cmd.iBlockLength = KMMCardHighCapBlockSize; //TRIM cmd blocklength
+ cmd.iCommand = ECmdTagEraseGroupStart;
+ break;
+ }
+
cmd.iBlockLength = s.iCardP->iCSD.EraseGroupSize();
if(cmd.iBlockLength == 0 || cmd.iTotalLength % cmd.iBlockLength != 0)
{
@@ -6123,7 +6286,7 @@
SMF_STATE(EStStartTagged)
OstTrace0( TRACE_INTERNALS, DMMCSTACK_CIMERASESM7, "EStStartTagged" );
- const TMMCCommandDesc& cmd = s.Command();
+ TMMCCommandDesc& cmd = s.Command();
TMMCCommandEnum command;
TUint endAddr = cmd.iArgument;
@@ -6134,20 +6297,29 @@
}
else
{
- if(cmd.IsBlockCmd())
- {
- endAddr += (cmd.iTotalLength - cmd.iBlockLength) >> KMMCardHighCapBlockSizeLog2;
- }
- else
- {
- endAddr += cmd.iTotalLength - cmd.iBlockLength;
- }
+ if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+ {
+ endAddr += cmd.IsBlockCmd() ? (cmd.iTotalLength / cmd.iBlockLength - 1) : (cmd.iTotalLength - cmd.iBlockLength);
+ command = ECmdTagEraseGroupEnd;
+ }
+ else
+ {
+ if(cmd.IsBlockCmd())
+ {
+ endAddr += (cmd.iTotalLength - cmd.iBlockLength) >> KMMCardHighCapBlockSizeLog2;
+ }
+ else
+ {
+ endAddr += cmd.iTotalLength - cmd.iBlockLength;
+ }
- command = ECmdTagEraseGroupEnd;
- }
-
- CurrentSessPushCmdStack();
+ command = ECmdTagEraseGroupEnd;
+ }
+ }
+
+ const TUint flags = cmd.iFlags;
s.FillCommandDesc( command, endAddr );
+ cmd.iFlags = flags; //Preserving current flags for TRIM
SMF_INVOKES( ExecCommandSMST, EStEndTagged )
SMF_STATE(EStEndTagged)
@@ -6159,7 +6331,16 @@
const TInt KMaxEraseTimeoutInSeconds = 30;
iBody->SetInactivityTimeout(KMaxEraseTimeoutInSeconds);
m.SetTraps(KMMCErrAll);
- s.FillCommandDesc( ECmdErase, 0 );
+
+ TMMCCommandDesc& cmd = s.Command();
+
+ if(cmd.iFlags & KMMCCmdFlagDeleteNotify)
+ {
+ s.FillCommandDesc(ECmdErase, KMMCCmdTrim);
+ }
+ else
+ s.FillCommandDesc( ECmdErase, 0 );
+
SMF_INVOKES( ExecCommandSMST, EStErased )
SMF_STATE(EStErased)
@@ -6602,6 +6783,9 @@
TMMCErr DMMCStack::AttachCardSMST( TAny* aStackP )
{ return( static_cast<DMMCStack *>(aStackP)->AttachCardSM() ); }
+TMMCErr DMMCStack::SwitchPartitionSMST( TAny* aStackP )
+ { return( static_cast<DMMCStack *>(aStackP)->SwitchPartitionSM() ); }
+
TMMCErr DMMCStack::ExecCommandSMST( TAny* aStackP )
{ return( static_cast<DMMCStack *>(aStackP)->ExecCommandSM() ); }
@@ -6689,8 +6873,6 @@
return new DMMCSession(aCallBack);
}
-EXPORT_C void DMMCStack::Dummy1() {}
-
/**
* Calls the PSL-implemented function SetBusWidth() if the bus width has changed
*
@@ -6743,8 +6925,14 @@
{
}
-EXPORT_C void DMMCStack::MachineInfo(TDes8& /*aMachineInfo*/)
- {
+EXPORT_C void DMMCStack::MachineInfo(TDes8& aMachineInfo)
+/**
+ * Default implementation of method. Calls
+ * DMMCStack::MachineInfo(TMMCMachineInfo& aMachineInfo)
+ */
+ {
+ TMMCMachineInfoV44Pckg& mi = static_cast<TMMCMachineInfoV44Pckg&> (aMachineInfo);
+ MachineInfo(mi());
}
TBusWidth DMMCStack::BusWidthEncoding(TInt aBusWidth) const
@@ -7560,3 +7748,39 @@
return r;
}
+/**
+ A generic adapter function for returning an interface of specified type
+ The caller should set aInterfacePtr to NULL before calling
+ @aInterfaceId Denotes the required interface to be returned
+ @aInterfacePtr On completion contains an interface of type specified by aInterfaceId
+ @aThis Extends the interface to provide further access to DMMCSession
+ */
+
+EXPORT_C TInt MMCGetExtInterface(TMMCExtInterfaceId aInterfaceId, MMCMExtInterface*& aInterfacePtr, TAny* /*aThis*/)
+ {
+ OstTrace1(TRACE_FLOW, MMCGETEXTINTERFACE_ENTRY, ">MMCGetExtInterface InterfaceId=%d", aInterfaceId );
+ TInt r = KErrNone;
+ switch(aInterfaceId)
+ {
+ case KInterfaceRpmb:
+ {
+ if (RpmbParmsPopulated)
+ {
+ aInterfacePtr = (MMCMExtInterface*)(&rpmbInfo);
+ }
+ else
+ {
+ // don't hand out interface if not ready to use
+ aInterfacePtr = NULL;
+ r = KErrNotReady;
+ }
+ break;
+ }
+ default:
+ aInterfacePtr = NULL;
+ break;
+ }
+ OstTrace0(TRACE_FLOW, MMCGETEXTINTERFACE_EXIT, "<MMCGetExtInterface" );
+ return r;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/pbus/mmc/stackdebug.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,56 @@
+// Copyright (c) 2010 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:
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define _STACK_DEBUG_PRINT_
+
+#if defined(_STACK_DEBUG_PRINT_) && (defined(_DEBUG) || defined(_DEBUG_RELEASE))
+/** Trace - format string */
+#define __PRINT(t) {Kern::Printf(t);}
+/** Trace - format string with 1 param */
+#define __PRINT1(t,a) {Kern::Printf(t,a);}
+/** Trace - format string with 2 params */
+#define __PRINT2(t,a,b) {Kern::Printf(t,a,b);}
+/** Trace - format string with 3 params */
+#define __PRINT3(t,a,b,c) {Kern::Printf(t,a,b,c);}
+/** Trace - format string with 4 params */
+#define __PRINT4(t,a,b,c,d) {Kern::Printf(t,a,b,c,d);}
+/** Trace - format string with 5 params */
+#define __PRINT5(t,a,b,c,d,e) {Kern::Printf(t,a,b,c,d,e);}
+
+#else
+
+/** NULL definition */
+#define __PRINT(t)
+/** NULL definition */
+#define __PRINT1(t,a)
+/** NULL definition */
+#define __PRINT2(t,a,b)
+/** NULL definition */
+#define __PRINT3(t,a,b,c)
+/** NULL definition */
+#define __PRINT4(t,a,b,c,d)
+/** NULL definition */
+#define __PRINT5(t,a,b,c,d,e)
+#endif
+
+#endif // DEBUG_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/rpmbdevice.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,434 @@
+// Copyright (c) 2010 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:
+// /os/kernelhwsrv/kernel/eka/drivers/rpmb/rpmbdevice.cpp
+// Kernel extension entry point for RPMB driver.
+//
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "../../include/drivers/locmedia_ost.h"
+#ifdef __VC32__
+#pragma warning(disable: 4127) // disabling warning "conditional expression is constant"
+#endif
+#include "rpmbdeviceTraces.h"
+#endif
+
+#include <kernel/kernel.h>
+#include <drivers/rpmbdevice.h>
+#include <drivers/sdcard.h>
+#include <drivers/sdio/sdio.h>
+#include <drivers/mmc.h>
+
+DRpmbDevice * DRpmbDevice::DRpmbDevicePtrs[KMaxPBusSockets*4] = {
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL};
+
+EXPORT_C DRpmbDevice::DRpmbDevice():
+ iSessionEndCallBack(DRpmbDevice::SessionEndCallBack, this),
+ iDeviceIndex(KIndexNotAssigned)
+ {
+ }
+
+EXPORT_C DRpmbDevice::~DRpmbDevice()
+ {
+ Close();
+ }
+
+void DRpmbDevice::SessionEndCallBack(TAny* aSelf)
+ {
+ DRpmbDevice& self = *static_cast<DRpmbDevice*>(aSelf);
+ self.DoSessionEndCallBack();
+ }
+
+void DRpmbDevice::DoSessionEndCallBack()
+ {
+ iSocket->EndInCritical();
+ Kern::SemaphoreSignal(*iRequestSemaphore);
+ }
+
+void DRpmbDevice::BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
+{
+ DRpmbDevice* device = (DRpmbDevice*)aPtr;
+ TPBusState busState = (TPBusState) (TInt) a1;
+ TInt busError = (TInt) a2;
+
+ if(aReason == TPBusCallBack::EPBusStateChange
+ && busState == EPBusOn && busError == KErrNone)
+ {
+ Kern::SemaphoreSignal(*(device->iPowerUpSemaphore));
+ }
+}
+
+TInt DRpmbDevice::PowerUpStack()
+ {
+ //
+ // Power up the socket - This ensures that the socket is powered up
+ // and the functions are re-enumerated.
+ //
+ iBusCallBack.iFunction = BusCallBack;
+ iBusCallBack.iPtr=this;
+ iBusCallBack.SetSocket(iSocket->iSocketNumber);
+ iBusCallBack.Add();
+ NKern::ThreadEnterCS();
+ TInt r = Kern::SemaphoreCreate(iPowerUpSemaphore,_L("RPMBPowerUpSem"), 0);
+ if(r == KErrNone)
+ {
+ TInt r = iSocket->PowerUp();
+ if(r==KErrNone)
+ {
+ Kern::SemaphoreWait(*iPowerUpSemaphore);
+ }
+ }
+ NKern::ThreadLeaveCS();
+ return r;
+ }
+
+void DRpmbDevice::SetSynchronisationParms(TUint8 aDeviceIndex)
+ {
+ // Mark this instance as being associated with the requested index
+ iDeviceIndex = aDeviceIndex;
+ // Mark the requested index as being associated with this instance
+ // Atomic operation ensures store is flushed from cache and committed
+ // to global memory
+ __e32_atomic_store_ord_ptr(&(DRpmbDevicePtrs[iDeviceIndex]),this);
+ }
+
+
+void DRpmbDevice::ClearSynchronisationParms()
+ {
+ // Serialise access to global pointer array and it's local index
+ NKern::FMWait(&iSynchronisationParmsMutex);
+ if (iDeviceIndex < KMaxPBusSockets*4)
+ {
+ // Atomic operation for load from global memory and not from cache
+ DRpmbDevice * ptrTableEntry =
+ (DRpmbDevice *)__e32_atomic_load_acq_ptr(&(DRpmbDevicePtrs[iDeviceIndex]));
+ // This instance of DRpmbDevice is associated with an index
+ // The associated index MUST be associated with this instance
+ __ASSERT_ALWAYS((ptrTableEntry == this), Kern::Fault(__FILE__, __LINE__));
+ // Disassociate index and instance
+ // Atomic operation ensures store is flushed from cache and committed
+ // to global memory
+ __e32_atomic_store_ord_ptr(&(DRpmbDevicePtrs[iDeviceIndex]),NULL);
+ iDeviceIndex = KIndexNotAssigned;
+ }
+ // Serialise access to global pointer array and it's local index
+ NKern::FMSignal(&iSynchronisationParmsMutex);
+ }
+
+EXPORT_C TInt DRpmbDevice::Open(TUint aDeviceIndex)
+ {
+ //
+ //eMMC4.4+ devices have RPMB partitions and each MMC device may be configured as having an RPMB
+ //partition in the baseport
+ //This function creates an MMC stack session for device aDeviceIndex
+ //This is used to access the RPMB partition on that device
+ //Extensions that use this interface during system startup should be located AFTER the RPMB and MMC
+ //extesnions in the system ROM and should not call this interface synchronously from a system
+ //startup initialisation routine
+ //aDeviceIndex the index of the device supporting the RPMB partition
+ //Returns KerrNone if successful
+ //Returns KErrNotReady if the baseport configuration hasn't been read yet
+ //Returns KErrNotSupported if the baseport configuration does not have a valid RPMB partition
+ //or RPMB is not supported by the media device
+ //Otherwise retruns a systemwide error code
+ //
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_1, "RPMB: >DrpmbDevice::Open");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::Open"));
+
+ TRpmbDeviceParms params;
+ params.iCardNumber = 0;
+ params.iSocketPtr = NULL;
+ MRpmbInfo* rpmbInterface = NULL;
+
+ TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface);
+ // MMCGetExtInterface currently returns KErrNotReady with rpmbInterface == NULL if the RPMB parameters
+ // haven't yet been populated
+ // proveided any calling extension is located AFTER the RPMB and MMC extesnions in the system ROM and
+ // does not call this interface synchronously from a system initialisation routine the following
+ // shouldn't be asserted
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_2, "RPMB: DrpmbDevice Get Interface err = %d", r);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice Get Interface err = %d", r));
+ __ASSERT_ALWAYS(r == KErrNone, Kern::Fault(__FILE__, __LINE__));
+
+ if (rpmbInterface == NULL)
+ {
+ // unexpected error since MMCGetExtInterface didn't return an error
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_3, "RPMB: DrpmbDevice Null rpmbInterface");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice Null rpmbInterface"));
+ return KErrGeneral;
+ }
+
+ // Interface currently supports a single device, device index = 0
+ r = rpmbInterface->RpmbInfo(aDeviceIndex, params);
+ if(r != KErrNone)
+ {
+ // requested index non zero or baseport not configured with RPMB capable MMC device
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_4, "RPMB: DrpmbDevice requested index non zero or baseport not configured, err = %d", r);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice requested index non zero or baseport not configured, err = %d", r));
+ return r;
+ }
+
+ iSocket = params.iSocketPtr;
+ // iSocket cannot be NULL
+ // TMMCardControllerInterface::RegisterMediaDevices ensures that the assigned value is not NULL
+ __ASSERT_ALWAYS((iSocket!=NULL), Kern::Fault(__FILE__, __LINE__));
+
+ // Serialise access to global pointer array and it's local index
+ NKern::FMWait(&iSynchronisationParmsMutex);
+
+ if (iDeviceIndex != KIndexNotAssigned)
+ {
+ // This instance of DRpmbDevice is already open
+ if (iDeviceIndex == aDeviceIndex)
+ {
+ // Serialise access to global pointer array and it's local index
+ NKern::FMSignal(&iSynchronisationParmsMutex);
+ // Already open with requested index
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_5, "RPMB: DrpmbDevice already open with requested index");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice already open with requested index"));
+ return KErrNone;
+ }
+ else
+ {
+ // Serialise access to global pointer array and it's local index
+ NKern::FMSignal(&iSynchronisationParmsMutex);
+ // Already open with other index
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_6, "RPMB: DrpmbDevice already open with other index");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice already open with other index"));
+ return KErrInUse;
+ }
+ }
+ else
+ {
+ // This instance of DRpmbDevice is not open
+
+ // Atomic operation for load from global memory and not from cache
+ DRpmbDevice * ptrTableEntry =
+ (DRpmbDevice *)__e32_atomic_load_acq_ptr(&(DRpmbDevicePtrs[aDeviceIndex]));
+
+ if (ptrTableEntry == NULL)
+ {
+ SetSynchronisationParms((TUint8)(aDeviceIndex));
+ }
+ else
+ {
+ // Requested index cannot be associated with this instance of DRpmbdevice
+ __ASSERT_ALWAYS(ptrTableEntry != this, Kern::Fault(__FILE__, __LINE__));
+ // Serialise access to global pointer array and it's local index
+ NKern::FMSignal(&iSynchronisationParmsMutex);
+ // Requested index already associated with a different instance of DRpmbDevice
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_7, "RPMB: DrpmbDevice requested index already associated with a different instance of DrpmbDevice");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice requested index already associated with a different instance of DrpmbDevice"));
+ return KErrInUse;
+ }
+ }
+ NKern::FMSignal(&iSynchronisationParmsMutex);
+
+ r = PowerUpStack();
+ if (r != KErrNone && r != KErrCompletion)
+ {
+ // Stack wasn't already powered up and failed to power up
+ ClearSynchronisationParms();
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_OPEN_8, "RPMB: DrpmbDevice wasn't already powered up and failed with err = %d", r);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DrpmbDevice wasn't already powered up and failed with err = %d", r));
+ return r;
+ }
+
+ DMMCStack* stack = iSocket->Stack(KBusNumber);
+ if(stack == NULL)
+ {
+ // KBusNumber = 0 so iSocket->Stack() returns iSocket->iStack
+ // Expect this to have been pre-assigned
+ // Expect a socket to be bound to a stack
+ ClearSynchronisationParms();
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_9, "RPMB: stack is NULL");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: stack is NULL"));
+ return KErrNoMemory;
+ }
+
+ iCard = stack->CardP(params.iCardNumber);
+ if(iCard == NULL)
+ {
+ // stack->CardP() returns stack->iCardArray->CardP(params.iCardNumber)
+ // Expect this to have been pre-assigned
+ // Expect card array to point to a card
+ ClearSynchronisationParms();
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_10, "RPMB: card pointer is NULL");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: card pointer is NULL"));
+ return KErrNoMemory;
+ }
+
+ NKern::ThreadEnterCS();
+ iSession = stack->AllocSession(iSessionEndCallBack);
+ NKern::ThreadLeaveCS();
+ if (iSession == NULL)
+ {
+ // DMMCStack::AllocSession() failed to create a new instance off DMMCSession
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_11, "RPMB: failed to create a new instance of DMMCSession");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: failed to create a new instance of DMMCSession"));
+ return KErrNoMemory;
+ }
+
+ iSession->SetStack(stack);
+ iSession->SetCard(iCard);
+
+ TInt bufLen, minorBufLen;
+ stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
+ // mmc media driver reserved the first KRpmbOneFramePacketLength bytes of the
+ // PSL buffer to be used for RPMB requests / responses
+ iIntBuf += minorBufLen;
+
+ if(iCard->ExtendedCSD().ExtendedCSDRev() < 5 || iCard->ExtendedCSD().RpmbSize() == 0)
+ {
+ // RPMB is not supported on selected hardware
+ ClearSynchronisationParms();
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_12, "RPMB: feature is not supported on selected hardware");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: feature is not supported on selected hardware"));
+ return KErrNotSupported;
+ }
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_OPEN_13, "RPMB: <DrpmbDevice::Open");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::Open"));
+ return KErrNone;
+ }
+
+EXPORT_C void DRpmbDevice::Close()
+ {
+ //
+ //Closes an interaction with an RPMB configured device
+ //
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_CLOSE_1, "RPMB: >DrpmbDevice::Close");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::Close"));
+
+ ClearSynchronisationParms();
+
+ iBusCallBack.Remove();
+
+ NKern::ThreadEnterCS();
+
+ if(iPowerUpSemaphore)
+ {
+ iPowerUpSemaphore->Close(NULL);
+ iPowerUpSemaphore = NULL;
+ }
+
+ if (iSession)
+ {
+ delete iSession;
+ iSession = NULL;
+ }
+
+ if(iRequestSemaphore)
+ {
+ iRequestSemaphore->Close(NULL);
+ iRequestSemaphore = NULL;
+ }
+
+ NKern::ThreadLeaveCS();
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_CLOSE_2, "RPMB: <DrpmbDevice::Close");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::Close"));
+ }
+
+EXPORT_C TInt DRpmbDevice::SendAccessRequest(TDes8& aRpmbRequest, TDes8& aRpmbResponse)
+ {
+ //
+ //sends a request to be handled by the RPMB partition
+ //aRpmbRequest - the physically contiguous region of memory containg the request to be handled
+ //aRpmbResponse - the physically contiguous region memory to where the response from the hardware will be written
+ //returns KErrNone if successful
+ //returns system wide epoc error code if set on call back from stack
+ //returns KErrArgument for invalid descriptor argument length
+ //returns KErrNotReady if not opened
+ //retruns KErrNotready if MMC stack is processing a posponed power down or a postponed media change event
+ //otherwise returns system wide error code
+ //
+
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_1, "RPMB: >DrpmbDevice::SendAccessRequest");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: >DrpmbDevice::SendAccessRequest"));
+
+ if ((aRpmbRequest.Length() != KRpmbOneFramePacketLength) || (aRpmbResponse.Length() != KRpmbOneFramePacketLength))
+ {
+ // insist on single frame access as mutiple read and multiple write (reliable write) notb yet supported
+ return KErrArgument;
+ }
+
+ if (iSession == NULL)
+ {
+ // DRpmbDevice::Open not called at all
+ // or not called after DRpmbDevice::Close
+ OstTrace0(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_2, "RPMB: DMMCSession is NULL");
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: DMMCSession is NULL"));
+ return KErrNotReady;
+ }
+
+ if (iRequestSemaphore == NULL)
+ {
+ // iRequestSemaphore zero filled prior to contruction
+ // create semaphore for waiting on stack
+ NKern::ThreadEnterCS();
+ TInt r = Kern::SemaphoreCreate(iRequestSemaphore,_L("RPMBRequestSemaphore"), 0);
+ NKern::ThreadLeaveCS();
+ if (r != KErrNone)
+ {
+ // failed to create semaphore
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_3, "RPMB: failed to create semaphore err = %d", r);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: failed to create semaphore err = %d", r));
+ return r;
+ }
+ }
+
+ memcpy(iIntBuf, aRpmbRequest.Ptr(), KRpmbOneFramePacketLength);
+
+ TInt r = iSocket->InCritical();
+ // may be KErrNotready if MMC stack is processing a posponed power down event or a postponed media change event
+ if (r == KErrNone)
+ {
+ iSession->SetPartition(TExtendedCSD::ESelectRPMB); //Set RPMB Partition
+ iSession->ResetCommandStack();
+ iSession->FillCommandArgs(KDeviceAddress, KRpmbOneFramePacketLength, iIntBuf, KRpmbOneFramePacketLength);
+ iSession->iSessionID = ECIMRpmbAccess;
+
+ r = iSession->Engage();
+ if(r == KErrNone)
+ {
+ Kern::SemaphoreWait(*iRequestSemaphore);
+ memcpy((TUint8 *)aRpmbResponse.Ptr(), iIntBuf, KRpmbOneFramePacketLength);
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_4, "RPMB: request complete with %d", iSession->EpocErrorCode());
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: request complete with %d", iSession->EpocErrorCode()));
+ return iSession->EpocErrorCode();
+ }
+ }
+
+ iSocket->EndInCritical();
+
+ OstTrace1(TRACE_FLOW, DRPMBDEVICE_SENDACCESSREQUEST_5, "RPMB: <DrpmbDevice::SendAccessRequest complete %d", r);
+ __KTRACE_OPT(KPBUS1, Kern::Printf("RPMB: <DrpmbDevice::SendAccessRequest complete %d", r));
+
+ return r;
+ }
+
+DECLARE_STANDARD_EXTENSION()
+ {
+ __KTRACE_OPT(KBOOT,Kern::Printf("RPMBEXT.DLL DECLARE_STANDARD_EXTENSION entry point"));
+ return KErrNone;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/rpmbext.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,55 @@
+// Copyright (c) 2010 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:
+// /os/kernelhwsrv/kernel/eka/drivers/rpmb/rpmbext.mmp
+// rpmbext.dll RPMB driver
+//
+//
+
+/**
+ @file
+*/
+
+#include "../../kernel/kern_ext.mmh"
+
+target rpmbext.dll
+targettype kext
+linkas rpmbext.dll
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+systeminclude ../../../include
+systeminclude ../../../include/drivers
+#endif
+
+USERINCLUDE traces
+
+source rpmbdevice.cpp
+
+library epbusmmc.lib
+
+capability all
+
+epocallowdlldata
+
+uid 0x1000008d 0x2003301C
+
+DEFFILE ../../~/rpmbext.def
+
+VENDORID 0x70000001
+
+start wins
+win32_headers
+end
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/rpmb/traces/OstTraceDefinitions.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,21 @@
+// 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:
+
+#ifndef __OSTTRACEDEFINITIONS_H__
+#define __OSTTRACEDEFINITIONS_H__
+// OST_TRACE_COMPILER_IN_USE flag has been added by Trace Compiler
+// REMOVE BEFORE CHECK-IN TO VERSION CONTROL
+//#define OST_TRACE_COMPILER_IN_USE
+#include <opensystemtrace.h>
+#endif
--- a/kernel/eka/eabi/epbusmu.def Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/eabi/epbusmu.def Mon Oct 11 19:11:06 2010 +0100
@@ -120,7 +120,7 @@
_ZTV7DMMCPsu @ 119 NONAME ; vtable for DMMCPsu
_ZTV9DMMCStack @ 120 NONAME ; vtable for DMMCStack
_ZN9DMMCStack22ModifyCardCapabilitySMEv @ 121 NONAME ; DMMCStack::ModifyCardCapabilitySM()
- _ZN9DMMCStack6Dummy1Ev @ 122 NONAME
+ _Z18MMCGetExtInterface18TMMCExtInterfaceIdRP16MMCMExtInterfacePv @ 122 NONAME
_ZN9DMMCStack12GetInterfaceENS_12TInterfaceIdERPNS_10MInterfaceE @ 123 NONAME
_ZN9DMMCStack11MachineInfoER5TDes8 @ 124 NONAME
_ZN9DMMCStack11SetBusWidthEm @ 125 NONAME
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/eabi/rpmbextu.def Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,12 @@
+EXPORTS
+ _ZN11DRpmbDevice17SendAccessRequestER5TDes8S1_ @ 1 NONAME
+ _ZN11DRpmbDevice4OpenEj @ 2 NONAME
+ _ZN11DRpmbDevice5CloseEv @ 3 NONAME
+ _ZN11DRpmbDeviceC1Ev @ 4 NONAME
+ _ZN11DRpmbDeviceC2Ev @ 5 NONAME
+ _ZN11DRpmbDeviceD0Ev @ 6 NONAME
+ _ZN11DRpmbDeviceD1Ev @ 7 NONAME
+ _ZN11DRpmbDeviceD2Ev @ 8 NONAME
+ _ZTI11DRpmbDevice @ 9 NONAME
+ _ZTV11DRpmbDevice @ 10 NONAME
+
--- a/kernel/eka/include/drivers/mmc.h Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/drivers/mmc.h Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -12,7 +12,7 @@
//
// Description:
// Generic MMC controller types and standard classes for MMC manipulation
-// This controller follows MMC spec V2.1
+// This controller follows MMC spec V4.4+
//
//
@@ -26,6 +26,7 @@
#include <drivers/pbus.h>
#include <d32locd.h>
+#include <drivers/rpmbpacket.h>
// MMC Card maximum system settings
@@ -56,7 +57,10 @@
class TMMCPasswordStore;
class TMMCEraseInfo;
class TMMCMachineInfoV4;
+class TMMCMachineInfoV44;
+typedef TPckg<TMMCMachineInfo> TMMCardMachineInfoPckg;
typedef TPckg<TMMCMachineInfoV4> TMMCMachineInfoV4Pckg;
+typedef TPckg<TMMCMachineInfoV44> TMMCMachineInfoV44Pckg;
enum TMMCAppCommand {EMMCNormalCmd,EMMCApplicationCmd};
@@ -104,10 +108,36 @@
*/
typedef TUint32 TMMCErr;
-// MMC Enums and inline functions
-
-
-
+/**
+A structure to define global parameters for the initialisation of an RPMB object.
+This is required for devices with emmc4.4+
+@internalComponent
+*/
+struct TRpmbDeviceParms
+ {
+ DMMCSocket* iSocketPtr;
+ TUint iCardNumber;
+ };
+
+/*
+ Global counter for number or RPMB partitions. Only one partition per device
+ */
+GLREF_D TUint NumberOfRpmbs;
+/*
+ Global holder for RPMB parameters
+ */
+GLREF_D TRpmbDeviceParms TheRpmbs[KMaxPBusSockets*4];
+
+GLREF_D TBool RpmbParmsPopulated;
+
+/**
+Max number of RPMB devices
+*/
+const TUint MaxIndexRpmb = 0;
+
+/**
+MMC Enums and inline functions
+*/
/**
@publishedPartner
@@ -570,6 +600,43 @@
/**
+ * Client InterfaceIDs for GetExtInterface
+ * @publishedPartner
+ *
+ */
+enum TMMCExtInterfaceId
+ {
+ KInterfaceRpmb
+ };
+
+class MMCMExtInterface
+ {
+public:
+ virtual TInt Func() = 0;
+ };
+
+/**
+Interface class to return information for an RPMB capable device.
+Used for emmc v4.4+
+*/
+
+class MRpmbInfo
+ {
+public:
+ virtual inline TInt RpmbInfo(TUint aDeviceIndex, TRpmbDeviceParms& aParams);
+ };
+
+/**
+ A generic adapter function for returning an interface of specified type
+ The caller should set aInterfacePtr to NULL before calling
+ @aInterfaceId Denotes the required interface to be returned
+ @aInterfacePtr On completion contains an interface of type specified by aInterfaceId
+ @aThis Extends the interface to provide further access to DMMCSession
+ */
+
+IMPORT_C TInt MMCGetExtInterface(TMMCExtInterfaceId aInterfaceId, MMCMExtInterface*& aInterfacePtr, TAny* aThis = NULL);
+
+/**
@publishedPartner
@released
@@ -626,10 +693,11 @@
ECIMLockStack =14,
ECIMInitStackAfterUnlock =15,
ECIMAutoUnlock =16,
- ECIMSleep =17
+ ECIMSleep =17,
+ ECIMRpmbAccess =18
};
-const TUint KMMCMaxSessionTypeNumber = 18;
+const TUint KMMCMaxSessionTypeNumber = 19;
const TUint KMMCMinCustomSession = 1024;
const TUint KMMCCmdDirDirBitPosition= KBit0; //fixed - dont change it
@@ -639,7 +707,7 @@
const TUint KMMCCmdDirWBitDirect= KBit7;
const TUint KMMCCmdReliableWrite = KBit31;
-
+const TUint KMMCCmdTrim = KBit0; //Trim command arg
/**
@publishedPartner
@@ -1463,7 +1531,7 @@
/**
Extended CSD register class.
For more information about this register, see the MultimediaCard System
- Specification, Version 4.1+
+ Specification, Version 4.4
@publishedPartner
@released
@@ -1503,10 +1571,28 @@
EBusWidthModeIndex = 183,
/** Offset of the BOOT_CONFIG field */
EBootConfigIndex = 179,
+ /** Offset of the BOOT_CONFIG_PROT field */
+ EBootConfigProtectionIndex = 178,
/** Offset of the BOOT_BUS_WIDTH field */
EBootBusWidthIndex = 177,
/** Offset of the ERASE_GROUP_DEF field */
- EEraseGroupDefIndex = 175
+ EEraseGroupDefIndex = 175,
+ /** Offset of the BOOT_WP field */
+ EBootAreaWriteProtectionIndex = 173,
+ /** Offset of the USER_WP field */
+ EUserAreaWriteProtectionIndex = 171,
+ /** Offset of the FW_CONFIG field */
+ EFwConfigIndex = 169,
+ /** Offset of the RST_n_FUNCTION field */
+ EHardwareResetFunctionIndex = 162,
+ /** Offset of the PARTITIONS_ATTRIBUTE field */
+ EPartitionsAttributeIndex = 156,
+ /** Offset of the PARTITION_SETTING_COMPLETED field */
+ EPartitionSettingIndex = 155,
+ /** Offset of the GP_SIZE_MULT field */
+
+
+
};
/**
@@ -1524,6 +1610,17 @@
/** Offset of the HC_ERASE_GRP_SIZE field */
EHighCapacityEraseGroupSizeIndex = 224
};
+
+ /** This enum defines the values for the Extended CSD Revision register */
+ enum TExtendedCSDRev
+ {
+ EExtendedCSDRev1_0 = 0,
+ EExtendedCSDRev1_1 = 1,
+ EExtendedCSDRev1_2 = 2,
+ EExtendedCSDRev1_3 = 3,
+ EExtendedCSDRev1_4 = 4,
+ EExtendedCSDRev1_5 = 5
+ };
/** This enum defines the bus width encoding used by the BUS_WIDTH field */
enum TExtCSDBusWidths
@@ -1547,15 +1644,21 @@
/**
This enum defines the boot config encoding used by the BOOT_CONFIG field
*/
- enum TExtCSDBootConfig
+ enum TExtCSDBootConfig // in v4.4 this is now called PARTITION_CONFIG
{
ESelectUserArea = 0x00,
ESelectBootPartition1 = 0x01,
ESelectBootPartition2 = 0x02,
+ ESelectRPMB = 0x03, // R/W Replay Protected Memory Block (RPMB)
+ ESelectGPAPartition1 = 0x04, // Access to General Purpose Area partition 1
+ ESelectGPAPartition2 = 0x05, // Access to General Purpose Area partition 2
+ ESelectGPAPartition3 = 0x06, // Access to General Purpose Area partition 3
+ ESelectGPAPartition4 = 0x07, // Access to General Purpose Area partition 4
EEnableBootPartition1forBoot = 0x08,
EEnableBootPartition2forBoot = 0x10,
EEnableUserAreaforBoot = 0x38,
- EEnableBootAck = 0x40
+ EEnableBootAck = 0x40,
+ EPartitionTestMode = 0x100 // Indicates test mode for eMMC partitions
};
/**
@@ -1698,6 +1801,9 @@
/** returns the contents of the BOOT_SIZE_MUTLI field */
inline TUint BootSizeMultiple() const;
+ /** returns the size of the boot partitions in sectors */
+ inline TUint32 BootSizeInSectors() const;
+
/** returns the contents of the ERASE_TIMEOUT_MULT field */
inline TUint EraseTimeoutMultiple() const;
@@ -1719,13 +1825,77 @@
/** returns True if the CARD_TYPE field conatains a valid value **/
inline TBool IsSupportedCardType() const;
+ /** returns the contents of the ERASED_MEM_CONT field */
+ inline TUint ErasedMemoryContent() const;
+
+ /** returns the contents of the BOOT_CONFIG_PROT field */
+ inline TUint BootConfigProt() const;
+
+ /** returns the contents of the BOOT_WP field */
+ inline TUint BootAreaWriteProtectionReg() const;
+
+ /** returns the contents of the USER_WP field */
+ inline TUint UserAreaWriteProtectionReg() const;
+
+ /** returns the contents of the FW_CONFIG field */
+ inline TUint FwConfiguration() const;
+
+ /** returns the RPMB size based on contents of the RPMB_SIZE_MULT field */
+ inline TUint32 RpmbSize() const;
+
+ /** returns the RPMB size in sectors */
+ inline TUint32 RpmbSizeInSectors() const;
+
+ /** returns the contents of the RST_n_FUNCTION field */
+ inline TUint HwResetFunction() const;
+
+ /** returns the contents of the PARTITIONING_SUPPORT field */
+ inline TUint PartitioningSupport() const;
+
+ /** returns the Max Enhanced Area Size base on the contents of the
+ MAX_ENH_SIZE_MULT field */
+ inline TUint32 MaxEnhancedAreaSize() const;
+
+ /** returns the contents of the PARTITIONS_ATTRIBUTE field */
+ inline TUint PartitionsAttribute() const;
+
+ /** returns the contents of the PARTITION_SETTING_COMPLETED field */
+ inline TUint PartitioningSetting() const;
+
+ /** returns the General purpose partition sizes based on contents of the
+ GP_SIZE_MULT fields */
+ inline TUint64 GeneralPurposePartition1Size() const;
+ inline TUint64 GeneralPurposePartition2Size() const;
+ inline TUint64 GeneralPurposePartition3Size() const;
+ inline TUint64 GeneralPurposePartition4Size() const;
+
+ /** returns the General Purpose Partition sizes in sectors */
+ inline TUint32 GeneralPurposePartition1SizeInSectors() const;
+ inline TUint32 GeneralPurposePartition2SizeInSectors() const;
+ inline TUint32 GeneralPurposePartition3SizeInSectors() const;
+ inline TUint32 GeneralPurposePartition4SizeInSectors() const;
+
+ /** returns the Enhanced User Data Area Size based on thec contents of the
+ ENH_SIZE_MULT fields */
+ inline TUint64 EnhancedUserDataAreaSize() const;
+
+ /** returns the Enhanced User Data Start Address based on the contents of
+ the ENH_START_ADDR fields */
+ inline TUint32 EnhancedUserDataStartAddress() const;
+
+ /** returns the contents of the SEC_BAD_BLK_MGMNT field */
+ inline TUint BadBlockManagementMode() const;
+
private:
+ inline TUint64 PartitionSize(TUint8 aMult0, TUint8 aMult1, TUint8 aMult2, TUint32 aMultiplier) const;
+
/**
@internalComponent little endian 512 byte field representing extended CSD
*/
TUint8 iData[KMMCExtendedCSDLength];
};
+const TInt KMMCSelectPartitionMask = KBit0 | KBit1 | KBit2;
// 32 bit MMC card status field (response R1)
@@ -1754,6 +1924,7 @@
const TUint32 KMMCStatErrOutOfRange= KBit31;
const TUint32 KMMCStatErrorMask= KMMCStatErrOutOfRange |
+ KMMCStatSwitchError |
KMMCStatErrAddressError |
KMMCStatErrBlockLenError|
KMMCStatErrEraseSeqError|
@@ -2113,6 +2284,8 @@
const TUint32 KMMCCmdFlagDoubleBuffer= KBit7; // The current DT command is double-buffered
const TUint32 KMMCCmdFlagPhysAddr= KBit8; // Address is a physical address
const TUint32 KMMCCmdFlagReliableWrite= KBit9; // Current command is Reliable Write
+const TUint32 KMMCCmdFlagDeleteNotify= KBit10; // Current command is Delete Notify
+const TUint32 KMMCCmdFlagRpmbIO= KBit11; // Current command is of RPMB type
const TUint32 KMMCCmdFlagASSPFlags= KMMCCmdFlagBytesValid |
KMMCCmdFlagTransStopped |
@@ -2948,6 +3121,11 @@
inline void SetupCIMWriteBlock(TMMCArgument aBlockAddr, TUint8* aMemoryP, TUint32 aBlocks = 1);
inline void SetupCIMEraseMSector(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
inline void SetupCIMEraseMGroup(TMMCArgument aBlockAddr, TUint32 aBlocks = 1);
+
+ // RPMB access macros setup
+ inline void SetupRpmbSendRequest(TBool aSetReliableWrite);
+ inline void SetupRpmbReceiveResponse();
+ inline void SetupRpmbSendReadResultRegisterRequest();
// Raw commands (must be used in the locked bus state only)
// Known commands with or without (with a default) argument
@@ -3008,6 +3186,9 @@
inline void PushCommandStack();
inline void PopCommandStack();
+
+ inline void SetPartition(TInt aPartition);
+ inline TInt Partition() const;
// Methods for double-buffered data transfer:
inline TBool RequestMoreData();
@@ -3061,8 +3242,10 @@
TMMCCallBack iDataTransferCallback; // A callback function, used to request more data when performing double-buffering
- TUint32 iSpare[21]; // Spare data (stolen from iCommand)
-
+ TUint32 iSpare[20]; // Spare data (stolen from iCommand)
+
+ TUint32 iPartition; // The targetted partition
+
TMMCard* iSavedCardP; // Saved copy of iCardP
TMMCStateMachine iMachine; // State Machine context
@@ -3496,6 +3679,8 @@
inline TMMCErr ProgramTimerSM();
static TMMCErr GoIdleSMST(TAny* aStackP);
inline TMMCErr GoIdleSM();
+ static TMMCErr SwitchPartitionSMST(TAny* aStackP);
+ inline TMMCErr SwitchPartitionSM();
static TMMCErr SwitchToLowVoltageSMST(TAny* aStackP);
@@ -3524,6 +3709,21 @@
static TMMCErr ExecBusTestSMST(TAny* aStackP);
inline TMMCErr ExecBusTestSM();
+ static TMMCErr CIMRpmbAccessSMST(TAny* aStackP);
+ TMMCErr CIMRpmbAccessSM();
+
+ static TMMCErr CIMRpmbWriteAuthenticationKeySMST(TAny* aStackP);
+ TMMCErr CIMRpmbWriteAuthenticationKeySM();
+
+ static TMMCErr CIMRpmbReadWrCounterSMST(TAny* aStackP);
+ TMMCErr CIMRpmbReadWrCounterSM();
+
+ static TMMCErr CIMRpmbWriteSMST(TAny* aStackP);
+ TMMCErr CIMRpmbWriteSM();
+
+ static TMMCErr CIMRpmbReadSMST(TAny* aStackP);
+ TMMCErr CIMRpmbReadSM();
+
enum TBusWidthAndClock
{
E1Bit20Mhz = 0x0000,
@@ -3616,11 +3816,6 @@
friend class DMMCSession;
friend class TMMCardArray;
-private:
- //
- // Dummy functions to maintain binary compatibility
- IMPORT_C virtual void Dummy1();
-
protected:
/**
Gets an interface from a derived class
@@ -3651,8 +3846,8 @@
-
class TMMCMachineInfo
+
/**
Platform-specific configuration information for the
MultiMediaCard stack.
@@ -3814,9 +4009,6 @@
-
-typedef TPckg<TMMCMachineInfo> TMMCardMachineInfoPckg;
-
/**
Platform-specific configuration information for the
MultiMediaCard stack. Contains information pertinent to
@@ -3874,6 +4066,43 @@
};
+
+/**
+ Platform-specific configuration information for the
+ MultiMediaCard stack. Contains information pertinent to
+ MMC specification version 4.4
+
+ An object of this type is passed to the Variant implementation
+ of DMMCStack::MachineInfo(), which should fill the public data
+ members with appropriate information and values.
+
+@internalComponent
+*/
+class TMMCMachineInfoV44 : public TMMCMachineInfoV4
+ {
+public:
+ inline TMMCMachineInfoV44() {memclr(this, sizeof(*this));}
+
+ /**
+ The version of the structure returned by the PSL in a call to
+ DMMStack::MachineInfo()
+ The fields defined in TMMCMachineInfoV44 are only valid if the
+ version is EVersion44 or higher
+ */
+ enum TVersion {EVersion3, EVersion4, EVersion44};
+
+ /**
+ Use iRpmbSlotCount and iRpmbSlotList to define a list of up to
+ four slots for devices containing an RPMB partitions to be
+ exposed
+ */
+ TUint iRpmbSlotCount;
+ TUint * iRpmbSlotList;
+
+ TUint8 iSpare[14];
+ };
+
+
class DMMCPsu : public DPBusPsuBase
/**
DPBusPsuBase derived abstract class to control the MMC socket's power supply.
@@ -4130,6 +4359,7 @@
EMMCInvalidCardNumber =19,
EMMCNotInDfcContext =20,
EMMCAddressCardNotSupported =21,
+ EMMCInvalidPartitionNumber =22
};
IMPORT_C static void Panic(TMMCPanic aPanic);
friend class DMMCStack;
--- a/kernel/eka/include/drivers/mmc.inl Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/drivers/mmc.inl Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -17,6 +17,9 @@
// outside the Kernel and Hardware Services package.
//
+const TInt KOneKiloByte = 1024;
+const TInt KSectorSize = 512;
+
/**
A static function that takes the 4 bytes that are stored in a memory location
@@ -180,6 +183,132 @@
inline TUint TExtendedCSD::SleepCurrentVccQ() const {return iData[219];}
inline TUint TExtendedCSD::SleepAwakeTimeout() const {return iData[217];}
+inline TUint TExtendedCSD::ErasedMemoryContent() const {return iData[181];}
+inline TUint TExtendedCSD::BootConfigProt() const {return iData[EBootConfigProtectionIndex];}
+inline TUint TExtendedCSD::BootAreaWriteProtectionReg() const {return iData[EBootAreaWriteProtectionIndex];}
+inline TUint TExtendedCSD::UserAreaWriteProtectionReg() const {return iData[EUserAreaWriteProtectionIndex];}
+inline TUint TExtendedCSD::FwConfiguration() const {return iData[EFwConfigIndex];}
+
+
+inline TUint32 TExtendedCSD::BootSizeInSectors() const
+ {
+
+ return BootSizeMultiple() * 128 * KOneKiloByte / KSectorSize;
+ }
+
+inline TUint32 TExtendedCSD::RpmbSize() const
+ {
+ return static_cast<TUint32>(iData[168]);
+ }
+
+inline TUint32 TExtendedCSD::RpmbSizeInSectors() const
+ {
+
+ return RpmbSize() * 128 * KOneKiloByte / KSectorSize;
+ }
+
+inline TUint TExtendedCSD::HwResetFunction() const {return iData[EHardwareResetFunctionIndex];}
+inline TUint TExtendedCSD::PartitioningSupport() const {return iData[160];}
+
+inline TUint32 TExtendedCSD::MaxEnhancedAreaSize() const
+ {
+ return(iData[157] |
+ (static_cast<TUint32>(iData[158]) << 8) |
+ (static_cast<TUint32>(iData[159]) << 16) *
+ HighCapacityWriteProtectGroupSize());
+ }
+
+inline TUint TExtendedCSD::PartitionsAttribute() const {return iData[EPartitionsAttributeIndex];}
+inline TUint TExtendedCSD::PartitioningSetting() const {return iData[EPartitionSettingIndex];}
+
+inline TUint64 TExtendedCSD::PartitionSize(TUint8 aMult0, TUint8 aMult1, TUint8 aMult2, TUint32 aMultiplier) const
+ {
+ TUint64 size = static_cast<TUint64>(aMult2) * 8 * 8;
+ size += static_cast<TUint64>(aMult1) * 8;
+ size += static_cast<TUint64>(aMult0);
+
+ size *= aMultiplier;
+ return size;
+ }
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition1Size() const
+ {
+ return PartitionSize(iData[143],
+ iData[144],
+ iData[145],
+ (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+ );
+ }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition1SizeInSectors() const
+ {
+ return I64LOW(GeneralPurposePartition1Size() / KSectorSize);
+ }
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition2Size() const
+ {
+ return PartitionSize(iData[146],
+ iData[147],
+ iData[148],
+ (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+ );
+ }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition2SizeInSectors() const
+ {
+ return I64LOW(GeneralPurposePartition2Size() / KSectorSize);
+ }
+
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition3Size() const
+ {
+ return PartitionSize(iData[149],
+ iData[150],
+ iData[151],
+ (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+ );
+ }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition3SizeInSectors() const
+ {
+ return I64LOW(GeneralPurposePartition3Size() / KSectorSize);
+ }
+
+inline TUint64 TExtendedCSD::GeneralPurposePartition4Size() const
+ {
+ return PartitionSize(iData[152],
+ iData[153],
+ iData[154],
+ (HighCapacityWriteProtectGroupSize() * HighCapacityEraseGroupSize() * 512 * 1024)
+ );
+
+ }
+
+inline TUint32 TExtendedCSD::GeneralPurposePartition4SizeInSectors() const
+ {
+ return I64LOW(GeneralPurposePartition4Size() / KSectorSize);
+ }
+
+inline TUint64 TExtendedCSD::EnhancedUserDataAreaSize() const
+ {
+ return PartitionSize(iData[140],
+ iData[141],
+ iData[142],
+ HighCapacityWriteProtectGroupSize()
+ );
+ }
+
+inline TUint32 TExtendedCSD::EnhancedUserDataStartAddress() const
+ {
+ // note, for HC devices this is in sectors, otherwise in bytes
+ return(iData[136] |
+ (static_cast<TUint32>(iData[137]) << 8) |
+ (static_cast<TUint32>(iData[138]) << 16) |
+ (static_cast<TUint32>(iData[139]) << 24));
+ }
+
+inline TUint TExtendedCSD::BadBlockManagementMode() const {return iData[134];}
+
// "Modes Segment" of Extended CSD - i.e. modifiable fields
inline TUint TExtendedCSD::CmdSet() const {return iData[ECmdSetIndex];}
inline TUint TExtendedCSD::CmdSetRev() const {return iData[ECmdSetRevIndex];}
@@ -944,6 +1073,33 @@
DMMCSocket::Panic(DMMCSocket::EMMCCommandStack));
}
+
+/**
+Sets the target partition access bits
+*/
+inline void DMMCSession::SetPartition(TInt aPartition)
+ {
+ TInt partition = aPartition & ~TExtendedCSD::EPartitionTestMode;
+ __ASSERT_DEBUG(
+ partition >= TExtendedCSD::ESelectUserArea &&
+ partition <= TExtendedCSD::ESelectGPAPartition4,
+ DMMCSocket::Panic(DMMCSocket::EMMCInvalidPartitionNumber));
+
+ iPartition = partition;
+ iPartition |= aPartition & TExtendedCSD::EPartitionTestMode;
+ }
+
+
+/**
+ * Returns the target partition
+ * @return The partition access identifier for which this session is destined
+*/
+inline TInt DMMCSession::Partition() const
+ {
+ return iPartition;
+ }
+
+
inline TMMCCommandDesc& DMMCSession::Command()
/**
* Returns the current command, as referred to by the stack pointer.
@@ -1041,6 +1197,66 @@
iSessionID = ECIMEraseGroup;
}
+inline void DMMCSession::SetupRpmbSendReadResultRegisterRequest()
+ {
+/**
+ * Sets the session to send an RPMB read result register request to the RPMB partition.
+ *
+ * Having set-up the session for this operation, the client must invoke, SMF_INVOKES. the
+ * read write state machine. CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result register read sequence by issuing the Write Multiple
+ * command, CMD25. Prior to this the state machine has issued CMD23 with the block count set
+ * to 1.
+ *
+ *
+ * All other RPMB request packets initiate an RPMB access and are constructed in the security code
+ * and sent to the stack via the security driver and the RPMB kernel extension DLL. The result
+ * register read request is used part ways through the program key and data write accesses to find
+ * out about the success of the particular operation. It is not sent via the RPMB kernel extension
+ * DLL so it is constructed here. Luckily it is easy to make.
+ */
+ TUint8* readRequestPtr = Command().iDataMemoryP;
+ memset(readRequestPtr, 0, KRpmbOneFramePacketLength);
+ * (readRequestPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadResultRegister;
+ SetupRpmbSendRequest(EFalse);
+ }
+
+inline void DMMCSession::SetupRpmbSendRequest(TBool aSetReliableWrite)
+/**
+ * Sets the session to send an RPMB request to the RPMB partition.
+ *
+ * Having set-up the session for this operation, the client must invoke, SMF_INVOKES, the
+ * read write state machine, CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result read sequence by issuing the Write Multiple
+ * command, CMD25. Prior to this the state machine has issued CMD23 with the block count set
+ * to 1 and optionally, if aSetReliableWrite is TRUE, with the arguement bit (31) set to 1.
+ */
+ {
+ iSessionID=ECIMWriteMBlock;
+ Command().iCommand = ECmdWriteMultipleBlock;
+ Command().iFlags |= KMMCCmdFlagRpmbIO;
+ if (aSetReliableWrite)
+ {
+ Command().iFlags |= KMMCCmdFlagReliableWrite;
+ }
+ }
+
+inline void DMMCSession::SetupRpmbReceiveResponse()
+/**
+ * Sets the session to receive an RPMB resposne from the RPMB partition.
+ *
+ * Having set-up the session for this operation, the client must invoke ,SMF_INVOKES. the
+ * read write state machine, CIMReadWriteBlocksSM, and the operation will commence. The read
+ * write state machine initiates the result read sequence by issuing the Read Multiple
+ * command, CMD18. Prior to this the state machine has issued CMD23 with the block count set
+ * to 1.
+ */
+ {
+ iSessionID=ECIMReadMBlock;
+ Command().iCommand = ECmdReadMultipleBlock;
+ Command().iFlags |= KMMCCmdFlagRpmbIO;
+ }
+
inline void DMMCSession::EnableDoubleBuffering(TUint32 aNumBlocks)
/**
* When called before a data transfer operation is engaged, specifies that the data
@@ -1555,3 +1771,34 @@
* @return ETrue if Erase Group commands are supported.
*/
{return(iEraseFlags&KMMCEraseGroupCmdsSupported);}
+
+/**
+Return RPMB information.
+@param aDeviceIndex The RPMB specific device index. Must be zero in current implementation
+@param aParams Retrieves the RPMB specific information required for initialisation
+*/
+
+inline TInt MRpmbInfo::RpmbInfo(TUint aDeviceIndex, TRpmbDeviceParms& aParams)
+ {
+ // note that MMCGetExtInterface doesn't hand out an instance of MRpmbInfo until
+ // RpmbParmsPopulated is true so baseport configuration has been read and any
+ // changes to NumberOfRpmbs and TheRpmbs are flushed
+ if (aDeviceIndex>MaxIndexRpmb)
+ {
+ // currently support just one RPMB capable device at index 0
+ return KErrGeneral;
+ }
+ else
+ {
+ if (NumberOfRpmbs==0)
+ {
+ // baseport configuration doesn't include an RPMB partition
+ return KErrNotSupported;
+ }
+ else
+ {
+ aParams = TheRpmbs[0];
+ return KErrNone;
+ }
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/drivers/rpmbdevice.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,66 @@
+// Copyright (c) 1994-2010 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:
+// eka\include\drivers\rpmb\rpmbdevice.h
+
+/**
+ @file
+ @internalTechnology
+*/
+
+
+#include <drivers/mmc.h>
+#include <e32cmn.h>
+
+const TUint KBusNumber = 0;
+const TUint KDeviceAddress = 0; //Address on card is not applicable to RPMB. This is handled on media device.
+const TUint8 KIndexNotAssigned = 0xFF;
+
+class DRpmbDevice : public DBase
+ {
+ public:
+
+ IMPORT_C DRpmbDevice();
+ IMPORT_C ~DRpmbDevice();
+ IMPORT_C TInt Open(TUint aDeviceIndex);
+ IMPORT_C TInt SendAccessRequest(TDes8 &aRpmbRequest, TDes8 &aRpmbResponse);
+ IMPORT_C void Close();
+
+ private:
+
+ static void SessionEndCallBack(TAny* aSelf);
+ static void BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
+ void DoSessionEndCallBack();
+ TInt PowerUpStack();
+ void SetSynchronisationParms(TUint8 aDeviceIndex);
+ void ClearSynchronisationParms();
+
+ DSemaphore* iPowerUpSemaphore;
+ DSemaphore* iRequestSemaphore;
+ NFastMutex iSynchronisationParmsMutex;
+
+ DMMCSession* iSession;
+ TMMCard* iCard;
+ DMMCSocket* iSocket;
+
+ TPBusCallBack iBusCallBack;
+ TMMCCallBack iSessionEndCallBack;
+
+ TUint8* iIntBuf;
+
+ TUint8 iDeviceIndex;
+ static DRpmbDevice* DRpmbDevicePtrs[KMaxPBusSockets*4];
+
+ TUint8 iSpare[10]; //for future use
+
+ };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/drivers/rpmbpacket.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,73 @@
+// Copyright (c) 2010 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:
+// eka\include\drivers\rpmb\rpmbpacket.h
+
+/**
+ @file
+ @internalTechnology
+ @prototype
+*/
+
+#ifndef RPMBPACKET_H
+#define RPMBPACKET_H
+
+// RPMB packet constants
+
+const TInt KRpmbOneFramePacketLength = 512;
+
+// request field offsets
+const TUint KRpmbRequestLsbOffset = 511;
+const TUint KRpmbRequestMsbOffset = 510;
+// request field values
+const TUint KRpmbRequestWriteKey = 0x0001;
+const TUint KRpmbRequestReadWriteCounter = 0x0002;
+const TUint KRpmbRequestWriteData = 0x0003;
+const TUint KRpmbRequestReadData = 0x0004;
+const TUint KRpmbRequestReadResultRegister = 0x0005;
+
+// response field offsets
+const TUint KRpmbResponseLsbOffset = 511;
+const TUint KRpmbResponseMsbOffset = 510;
+// response field values
+const TUint KRpmbResponseWriteKey = 0x0100;
+const TUint KRpmbResponseReadWriteCounter = 0x0200;
+const TUint KRpmbResponseWriteData = 0x0300;
+const TUint KRpmbResponseReadData = 0x0400;
+
+// result field offsets
+const TUint KRpmbResultLsbOffset = 509;
+const TUint KRpmbResultMsbOffset = 508;
+// result field counter expired mask
+const TUint KRpmbResultCounterExpiredMask = 0x007F;
+// result field values
+const TUint KRpmbResultOk = 0x0000;
+const TUint KRpmbResultGeneralFailure = 0x0001;
+const TUint KRpmbResultAuthenticationFailure = 0x0002;
+const TUint KRpmbResultKeyNotProgrammed = 0x0007;
+
+// counter field offsets
+const TUint KRpmbCounterByteOneOffset = 503;
+const TUint KRpmbCounterByteTwoOffset = 502;
+const TUint KRpmbCounterByteThreeOffset = 501;
+const TUint KRpmbCounterByteFourOffset = 500;
+
+// key field
+const TUint KRpmbKeyLength = 32;
+const TUint KRpmbKeyOffset = 196;
+
+// data field
+const TUint KRpmbDataLength = 256;
+const TUint KRpmbDataOffset = 228;
+
+#endif /* #ifndef RPMBPACKET_H */
\ No newline at end of file
--- a/kernel/eka/include/e32ver.h Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/include/e32ver.h Mon Oct 11 19:11:06 2010 +0100
@@ -28,7 +28,7 @@
const TInt KE32MajorVersionNumber=2;
const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=4008;
+const TInt KE32BuildVersionNumber=4009;
const TInt KMachineConfigurationMajorVersionNumber=1;
const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/release.txt Mon Oct 11 17:54:41 2010 +0100
+++ b/kernel/eka/release.txt Mon Oct 11 19:11:06 2010 +0100
@@ -1,3 +1,20 @@
+Version 2.00.4009
+=================
+(Made by fadhliM 07/10/2010)
+
+1. hengrant
+ 1. RP 531855 eMMC 4.4 User Data Partitions
+ REQ 417-54821 MMC v4.4 support for eMMC (Bridge M4)
+ SUB 417-73300 eMMC V4.4
+ SUB 417-73303 eMMC v4.4 - User-Data partitions with Enhanced Attributes Support
+ 2. RP 529139 eMMC 4.4 RPMB
+ REQ 417-75165 MMC v4.4 support for eMMC (Bridge M5)
+ SUB 417-59932 eMMC v4.4 - Replay Protected Memory Block (RPMB) support
+ 3. RP 543420
+ REQ 417-75165 MMC v4.4 support for eMMC (Bridge M5)
+ SUB 417-73302 eMMC v4.4 - TRIM Support
+
+
Version 2.00.4008
=================
(Made by fadhliM 05/10/2010)
@@ -38,7 +55,9 @@
(Made by vfebvre 27/09/2010)
1. erifung
- 1. RP540323 REQ:405-4716 kernel side device driver staged shutdown feature
+ 1. RP 540346
+ REQ 405-4716 Staged shutdown server monitor
+ SUB 417-75212 Staged shutdown server monitor - kernel-side component
Version 2.00.4005
@@ -49,7 +68,10 @@
1. ou1cimx1#584587 PRM RBusDevResManUs::ChangeResourceState() to set a resource level to "0", causes FAULT: RESMANUS 0x000001e3 (483)
2. seolney
- 1. ou1cimx1#553109 REQ 405-4716, Feature 405-5174: Staged shutdown server monitor
+ 1. RP 506754
+ REQ 405-4716 Staged shutdown server monitor
+ SUB 417-75146 Shutdown Monitor: Domain Manager
+ ou1cimx1#553109 REQ 405-4716, Feature 405-5174: Staged shutdown server monitor
3. necliffo
1. ou1cimx1#584508 Improve Code Coverage for LocalMedia Subsystem and MMC Stack
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/rombuild/rpmbtest.oby Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 2010 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:
+*
+*/
+#define BASE_ROM
+#include <rom\##VARIANT##\header.iby>
+
+files=
+
+#include <rom\##VARIANT##\kernel.iby>
+#include "user.iby"
+#include <rom\hal\hal.iby>
+#include <rom\f32\f32.iby>
+
+// And now the t_rpmb test
+#include <rom##E32PATH##\kernelhwsrv\kerneltest\e32test\rpmb\##MAIN##test.iby>
+
+data=\epoc32\rom\e32test\rpmb\autoexec.bat \autoexec.bat
\ No newline at end of file
--- a/kerneltest/e32test/group/t_mmcdrv.mmp Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/e32test/group/t_mmcdrv.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -17,6 +17,7 @@
TARGET t_mmcdrv.exe
TARGETTYPE EXE
+USERINCLUDE ../../../kernel/eka/drivers/medmmc
SOURCEPATH ../pccd
SOURCE t_mmcdrv.cpp
LIBRARY euser.lib
--- a/kerneltest/e32test/pccd/t_mmcdrv.cpp Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/e32test/pccd/t_mmcdrv.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -13,10 +13,12 @@
// Description:
// e32test\pccd\t_mmcdrv.cpp
// Test the MultiMediaCard (MMC) media driver
-// Spare Test case Numbers 0513-0519
+// Spare Test case Numbers 0515-0519
//
//
+#define __E32TEST_EXTENSION__
+
#include "../mmu/d_sharedchunk.h"
#include <e32test.h>
#include <e32svr.h>
@@ -1860,8 +1862,122 @@
test(SecThreadChangeFlag==EFalse); // Closed 2nd thread so shouldn't have been updated
}
+// Helper function for eMMC partition switching test - writes test data
+TInt EMmcPartitionWriteTestData(const TInt aDriveNumber, const TChar aDataPattern)
+ {
+ TBusLocalDrive drv;
+ TBool chg(EFalse);
+
+ TInt r = drv.Connect(aDriveNumber, chg);
+ test(r == KErrNone);
+
+ TBuf8<KDiskSectorSize> buffer;
+
+ // write pattern to sector 0
+ buffer.Fill(aDataPattern, KDiskSectorSize);
+ r = drv.Write((TInt64) 0, buffer);
+
+ return r;
+ }
+
+// Helper function for eMMC partition switching test - reads test data
+TInt EMmcPartitionReadTestData(const TInt aDriveNumber, TDes8& aData)
+ {
+ // read pattern from sector 0
+ TBusLocalDrive drv;
+ TBool chg(EFalse);
+
+ TInt r = drv.Connect(aDriveNumber, chg);
+ test(r == KErrNone);
+
+ aData.Fill(0x00, aData.MaxSize());
+ r = drv.Read((TInt64) 0, aData.MaxSize(), aData);
+
+ drv.Disconnect();
+ return r;
+ }
+
+// Helper function for eMMC partition switching test - compares data to expected pattern
+TInt EMmcPartitionReadAndCompareTestData(const TInt aDriveNumber, const TChar aExpectedPattern)
+ {
+ TBuf8<KDiskSectorSize> actual;
+ TBuf8<KDiskSectorSize> expected;
+ TInt r = EMmcPartitionReadTestData(aDriveNumber, actual);
+ test(r == KErrNone);
+
+ expected.Fill(aExpectedPattern, KDiskSectorSize);
+
+ if(expected.Compare(actual) != 0)
+ {
+ test.Printf(_L("ERROR: Comparison failed. Expected:\n"));
+ DumpBuffer(expected);
+ test.Printf(_L("\nActual:\n"));
+ DumpBuffer(actual);
+ r = KErrGeneral;
+ }
+
+ return r;
+ }
+
+
+
+/**
+@SYMTestCaseID 0514 (taken from spare test case IDs)
+@SYMTestCaseDesc Test low-level partition switching capability
+@SYMTestPriority normal
+
+@SYMTestActions
+ a) Precondition: Valid partitions have been flashed to BOOT 1 and BOOT 2,
+ these have to be mapped correctly in variantmediadef.h
+ b) Write Data Pattern 1 to BOOT 1
+ c) Write Data Pattern 2 to BOOT 2
+ d) Read data from BOOT 1 and compare to DP1 - test passes if data matches
+ e) Write Data Pattern 3 to BOOT 1, at the same offset as in b)
+ f) Read data from BOOT 2 and compare to DP2 - test passes if data matches
+
+@SYMTestExpectedResults All tests must pass
+*/
+void TestPartitionSwitching()
+ {
+ const TInt KDriveBoot1 = 4; // see variantmediadef.h
+ const TInt KDriveBoot2 = 5;
+ const TChar KDataPattern1 = 0xD1;
+ const TChar KDataPattern2 = 0xD2;
+ const TChar KDataPattern3 = 0xD3;
+
+ test.Start(_L("eMMC partition switching"));
+
+ // Write data data pattern 1 to boot1
+ test.Printf(_L("Writing Data Pattern 1 to BOOT 1\n"));
+ TInt r = EMmcPartitionWriteTestData(KDriveBoot1, KDataPattern1);
+ test(r == KErrNone);
+
+ // Write data data pattern 2 to boot2
+ test.Printf(_L("Writing Data Pattern 2 to BOOT 2\n"));
+ r = EMmcPartitionWriteTestData(KDriveBoot2, KDataPattern2);
+ test(r == KErrNone);
+
+ // Read back data from boot 1 and compare it to previously written pattern
+ test.Printf(_L("Reading from BOOT 1\n"));
+ r = EMmcPartitionReadAndCompareTestData(KDriveBoot1, KDataPattern1);
+ test(r == KErrNone);
+
+ // Write data data pattern 3 to boot1
+ test.Printf(_L("Writing Data Pattern 3 to BOOT 1\n"));
+ r = EMmcPartitionWriteTestData(KDriveBoot1, KDataPattern3);
+ test(r == KErrNone);
+
+ // Read back data from boot 2 and compare it to previously written pattern
+ test.Printf(_L("Reading from BOOT 2\n"));
+ r = EMmcPartitionReadAndCompareTestData(KDriveBoot2, KDataPattern2);
+ test(r == KErrNone);
+
+ test.End();
+ }
//// End of Test
+
+
void Format()
//
// Format current drive
@@ -2203,39 +2319,53 @@
goto doorTest;
#endif
+ if(ManualMode)
+ {
+ // Only test in manual mode, as the rom needs special prep anyway (drive registration
+ // in variantmediadef.h and flashing of BB5 partition info structures using mmcloader)
+ // It is possible that as a result of the changes to variantmediadef.h the
+ // drive-number-to-letter mapping in the appropriate estart.txt may have to be adjusted
+ // as well
+ TestPartitionSwitching();
+ }
+
for(TInt pass = 0; pass < TMMCDrive::EMaxTestModes; pass++)
{
TInt r = KErrNone;
+
switch (pass)
{
- case 0 : r = TheMmcDrive.SetTestMode(TMMCDrive::ETestPartition); break;
- case 1 :
+ case TMMCDrive::ETestPartition :
+ r = TheMmcDrive.SetTestMode(TMMCDrive::ETestPartition);
+ break;
+
+ case TMMCDrive::ETestWholeMedia :
// don't trash partition table in automated mode because...
// cards in test rigs have often got deliberately small partition sizes to testing (!)
if (!ManualMode)
continue;
r = TheMmcDrive.SetTestMode(TMMCDrive::ETestWholeMedia);
break;
- case 2 : {
- r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemory);
- AllocateSharedBuffers(EFalse,EFalse);
- break;
- }
- case 3 : {
- r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryCache);
- AllocateSharedBuffers(EFalse, ETrue);
- break;
- }
- case 4 : {
- r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFrag);
- AllocateSharedBuffers(ETrue, EFalse);
- break;
- }
- default: {
- r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFragCache);
- AllocateSharedBuffers(ETrue, ETrue);
- break;
- }
+
+ case TMMCDrive::ETestSharedMemory :
+ r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemory);
+ AllocateSharedBuffers(EFalse,EFalse);
+ break;
+
+ case TMMCDrive::ETestSharedMemoryCache :
+ r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryCache);
+ AllocateSharedBuffers(EFalse, ETrue);
+ break;
+
+ case TMMCDrive::ETestSharedMemoryFrag :
+ r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFrag);
+ AllocateSharedBuffers(ETrue, EFalse);
+ break;
+
+ default:
+ r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFragCache);
+ AllocateSharedBuffers(ETrue, ETrue);
+ break;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/bld.inf Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 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:
+// e32test/rpmb/bld.inf
+// Kernel and User library test code
+//
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+PRJ_TESTEXPORTS
+
+rpmbtestautoexec.bat \epoc32\rom\e32test\rpmb\autoexec.bat
+
+PRJ_TESTMMPFILES
+
+t_rpmb
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/bld.inf Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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:
+// e32test/rpmb/driver/bld.inf
+// Kernel and User library test code
+//
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+PRJ_TESTEXPORTS
+
+PRJ_TESTMMPFILES
+
+d_rpmb support
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,1225 @@
+// Copyright (c) 2010 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:
+// e32test/rpmb/d_rpmb.cpp
+// LDD for testing RPMB kernel extension
+//
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include "d_rpmb.h"
+#include "../t_rpmb.h"
+
+_LIT(KRpmbTestThreadName,"RpmbTestThread");
+const TInt KRpmbTestPriority = 24;
+
+TDfcQue RpmbTestDfcQ;
+TDfc* DfcPtr;
+
+// please read this before uncommenting out #define RPMBTESTS_TRY_TO_WRITE_KEY:
+// Don't want to write key 'pre production' on real device as this will lock
+// the system out of the RPMB partition (the key should be preprogrammed as
+// part of the production process so that the system has access to the key -
+// if the key has already been written it can't be written again).
+// #define RPMBTESTS_TRY_TO_WRITE_KEY
+
+
+/****************************************
+ Implementation of DRpmbTestFactory class
+*****************************************/
+
+DRpmbTestFactory::DRpmbTestFactory()
+ {
+ }
+
+DRpmbTestFactory::~DRpmbTestFactory()
+ {
+ }
+
+TInt DRpmbTestFactory::Create(DLogicalChannelBase*& aChannel)
+ {
+ aChannel = new DRpmbTest;
+ return KErrNone;
+ }
+
+TInt DRpmbTestFactory::Install()
+ {
+ return SetName(&KRpmbTestLddName);
+ }
+
+void DRpmbTestFactory::GetCaps(TDes8& /*aDes*/) const
+// implementation required since DLogicalDevice::GetCaps is pure virtual
+ {
+ // do nothing
+ }
+
+
+static void RpmbTestDfcFunction(TAny* /*aPtr*/)
+ {
+ DRpmbDevice * rpmb;
+ rpmb = new DRpmbDevice;
+ TInt r = rpmb->Open(0);
+ Kern::Printf("%S Early on DRpmbDevice::Open test returned %d",&KDRpmbTestBanner, r);
+ // ASSERT to indicate test failure if DRpmbDevice::Open() returned error
+ __ASSERT_ALWAYS((r==KErrNone), Kern::Fault(__FILE__, __LINE__));
+ rpmb->Close();
+ delete rpmb;
+ // run more extensive tests early on
+ // note the unconventional use of a class derived from DLogicalChannelBase which is justified
+ // in the current context to provide more startup test coverage
+ DRpmbTest * test;
+ test = new DRpmbTest;
+ // while a call to DRpmbTest::DRpmbDeviceTests() works in this context
+ // a call to DRpmbTest::RpmbStackTests() would fail as DRpmbTest::DoCreate() wouldn't be
+ // called so that DRpmbTest::iStackSemPtr wouldn't get set up properly so that when it
+ // was uaed an exception would be generated
+ r = test->DRpmbDeviceTests();
+ Kern::Printf("%S Early on DRpmbTest::DRpmbDeviceTests() returned %d",&KDRpmbTestBanner, r);
+ // ASSERT to indicate test failure
+ __ASSERT_ALWAYS((r==KErrNone), Kern::Fault(__FILE__, __LINE__));
+ // not safe to delete test as not setup conventionally DRpmbTest::DoCreate() wasn't called
+ // at setup and DLogicalChannelBase::~DLogicalChannelBase__sub_object() would generate an
+ // exception
+ }
+
+
+/********************************
+ Entry point for RPMB test driver
+*********************************/
+
+DECLARE_STANDARD_EXTENSION()
+ {
+ TInt r = Kern::DfcQInit(&RpmbTestDfcQ,KRpmbTestPriority,&KRpmbTestThreadName);;
+ if (r != KErrNone)
+ return r;
+ DfcPtr = new TDfc(RpmbTestDfcFunction,NULL, &RpmbTestDfcQ, KMaxDfcPriority-7);
+ DfcPtr->Enque();
+ return KErrNone;
+ }
+
+DECLARE_EXTENSION_LDD()
+ {
+ return new DRpmbTestFactory;
+ }
+
+/*********************************
+ Implementation of DRpmbTest class
+**********************************/
+
+DRpmbTest::DRpmbTest():
+// initialise parameters
+ iStackSemPtr(NULL),
+ iPowerSemPtr(NULL),
+ iSessionEndCallBack(DRpmbTest::StackCallBack, this)
+ {
+ }
+
+DRpmbTest::~DRpmbTest()
+ {
+
+ iBusCallBack.Remove();
+
+ if (iPowerSemPtr)
+ {
+ iPowerSemPtr->Close(NULL);
+ }
+ if (iStackSemPtr)
+ {
+ iStackSemPtr->Close(NULL);
+ }
+ if (iSession)
+ {
+ delete iSession;
+ }
+ }
+
+TInt DRpmbTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
+ {
+ TInt r = KErrNone;
+ r = Kern::SemaphoreCreate(iStackSemPtr, _L("DRpmbStackSem"), 0);
+ return r;
+ }
+
+TInt DRpmbTest::Request(TInt aFunction, TAny* /*a1*/, TAny* /*a2*/)
+ {
+ TInt r = KErrNotSupported;
+ switch (aFunction)
+ {
+ case RTestRpmb::ERunTests:
+ {
+ // respond to user side request
+ // execute tests for RPMB kernel extension
+ // run standatd tests that use the DRpmbDevice interface
+ Kern::Printf(" ");
+ Kern::Printf("%S << START DRpmbDevice TESTS >>", &KDRpmbTestBanner);
+ r = DRpmbDeviceTests();
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S DPrmbDevice test FAILED", &KDRpmbTestBanner);
+ break;
+ }
+ Kern::Printf("%S >> ALL DRpmbDevice TESTS PASSED", &KDRpmbTestBanner);
+ // run tests that use the MMC stack bypassing the RPMB kernel extension
+ Kern::Printf(" ");
+ Kern::Printf("%S << START STACK TESTS >>", &KDRpmbTestBanner);
+ r = RpmbStackTests();
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S stack test FAILED", &KDRpmbTestBanner);
+ break;
+ }
+ Kern::Printf("%S >> ALL STACK TESTS PASSED", &KDRpmbTestBanner);
+ break;
+ }
+ default:
+ break;
+ }
+ return r;
+ }
+
+
+// test RPMB using the DRpmbDevice interface
+TInt DRpmbTest::DRpmbDeviceTests()
+// open interface and make data write, ket write, counter read and data write accesses
+ {
+ TInt size = (TInt)(2*KRpmbOneFramePacketLength);
+
+ NKern::ThreadEnterCS();
+ iRequest = (TUint8 *)Kern::Alloc(size);
+ NKern::ThreadLeaveCS();
+
+ iResponse = iRequest + KRpmbOneFramePacketLength;
+
+ TInt r = SendAccessRequestNotOpen();
+
+ if (r==KErrNone)
+ {
+ r = OpenWithBadIndex();
+ }
+
+ if (r==KErrNone)
+ {
+ r = MultipleOpen();
+ }
+
+ if (r==KErrNone)
+ {
+ r = iRpmb.Open(0);
+ }
+
+ if (r!=KErrNone)
+ {
+ Kern::Printf("%S DRpmbTest::DRpmbDeviceTest DRpmbDevice open error = %d",
+ &KDRpmbTestBanner, r);
+ }
+ else
+ {
+ r = SendAccessRequestBadParms();
+ }
+
+ if (r==KErrNone)
+ {
+ r = InvalidRequestId();
+ }
+
+ if (r==KErrNone)
+ {
+ r = IsKeyProgrammed();
+ }
+
+// Don't want to write key 'pre production' on real device as this will lock
+// the system out of the RPMB partition (the key should be preprogrammed as
+// part of the production process so that the system has access to the key -
+// if the key has already been written it can't be written again)
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if (r==KErrNone)
+ {
+ r = WriteKey();
+ }
+#endif
+
+ if (r==KErrNone)
+ {
+ r = ReadWriteCounter();
+ }
+
+ if (r==KErrNone)
+ {
+ r = ReadData();
+ }
+
+ iRpmb.Close();
+
+ NKern::ThreadEnterCS();
+
+ Kern::Free(iRequest);
+
+ NKern::ThreadLeaveCS();
+
+ return r;
+}
+
+TInt DRpmbTest::SendAccessRequestNotOpen()
+// test cases where DRpmbDevice::SendAccessRequest() is called
+// 1.) before DRpmbDevice::Open() is ever called
+// 2,) after DRpmbDevice::Close() has been called but before DRpmbDevice::Open() is called
+ {
+ Kern::Printf("%S DRpmbDevice::SendAccessRequest not open test", &KDRpmbTestBanner);
+ // wrap up IO buffers in descriptors to pass across interface
+
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+
+ // test call DRpmbDevice::SendAccessRequest before EVER calling open
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrNotReady)
+ {
+ Kern::Printf("%S SendAccessRequest not open test, before EVER opening, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ // test open and close and call again
+ r = iRpmb.Open(0);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S SendAccessRequest not open test, opening, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+ iRpmb.Close();
+
+ r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrNotReady)
+ {
+ Kern::Printf("%S SendAccessRequest not open test, before opening AFTER closing, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ Kern::Printf("%S DRpmbDevice::SendAccessRequest not open test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+}
+
+
+TInt DRpmbTest::OpenWithBadIndex()
+// test case where DRpmbDevice::Open() is called with a device index of more than zero
+ {
+ Kern::Printf("%S DRpmbDevice::Open bad index test", &KDRpmbTestBanner);
+
+ // test index > 0
+ TInt r = iRpmb.Open(1);
+ if (r != KErrGeneral)
+ {
+ Kern::Printf("%S RpmbDevice::Open bad index test, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ Kern::Printf("%S DRpmbDevice::Open bad index test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+}
+
+
+TInt DRpmbTest::MultipleOpen()
+// test case where DRpmbDevice::Open() is called twice with the same index parameter and
+// the same instance of DRpmbDevice
+// test case where DRpmbDevice::Open() is called twice with the same index parameter and
+// a different instance of DRpmbDevice
+ {
+ Kern::Printf("%S DRpmbDevice::Open use more than once test", &KDRpmbTestBanner);
+
+ TInt r = iRpmb.Open(0);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S RpmbDevice::Open use more than once test first open, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ r = iRpmb.Open(0);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S RpmbDevice::Open use more than once test second open, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ r = iRpmbSecondInstance.Open(0);
+ if (r != KErrInUse)
+ {
+ Kern::Printf("%S RpmbDevice::Open use more than once test third open, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ iRpmb.Close();
+ iRpmbSecondInstance.Close();
+
+ Kern::Printf("%S DRpmbDevice::Open use more than once test PASS", &KDRpmbTestBanner);
+
+ return KErrNone;
+ }
+
+
+TInt DRpmbTest::SendAccessRequestBadParms()
+// test cases where DRpmbDevice::SendAccessRequest is called with secriptor arguments with invalid lengths
+ {
+ Kern::Printf("%S DRpmbDevice::SendAccessRequest bad parms test", &KDRpmbTestBanner);
+
+ // test both lengths != KRpmbOneFramePacketLength
+ TBuf<KRpmbOneFramePacketLength-1> request;
+ TBuf<KRpmbOneFramePacketLength+1> response;
+ request.SetLength(KRpmbOneFramePacketLength-1);
+ response.SetLength(KRpmbOneFramePacketLength+1);
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrArgument)
+ {
+ Kern::Printf("%S SendAccessRequest bad parms test, both params bad, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ // test request length != KRpmbOneFramePacketLength
+ TBuf<KRpmbOneFramePacketLength+1> request1;
+ TBuf<KRpmbOneFramePacketLength> response1;
+ request1.SetLength(KRpmbOneFramePacketLength+1);
+ response1.SetLength(KRpmbOneFramePacketLength);
+
+ r = iRpmb.SendAccessRequest(request1, response1);
+ if (r != KErrArgument)
+ {
+ Kern::Printf("%S SendAccessRequest bad parms test, request param bad, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ // test response length !=KRpmbOneFramePacketLength
+ TBuf<KRpmbOneFramePacketLength> request2;
+ TBuf<KRpmbOneFramePacketLength-1> response2;
+ request2.SetLength(KRpmbOneFramePacketLength);
+ response2.SetLength(KRpmbOneFramePacketLength-1);
+
+ r = iRpmb.SendAccessRequest(request1, response1);
+ if (r != KErrArgument)
+ {
+ Kern::Printf("%S SendAccessRequest bad parms test, response param bad, unexpected error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+
+ Kern::Printf("%S DRpmbDevice::SendAccessRequest bad parms test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+}
+
+TInt DRpmbTest::InvalidRequestId()
+// send a request with an invalid request ID to the RPMB partition
+// when SendAccessRequest returns iResponse should not have reponse or result fields filled in
+ {
+ Kern::Printf("%S invalid request ID test", &KDRpmbTestBanner);
+
+ // set up write request packet with blank MAC
+ memset(iRequest, 0, KRpmbOneFramePacketLength);
+ * (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadResultRegister + 1;
+
+ // wrap up IO buffers in descriptors to pass across interface
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S invalid request ID test, send request error = %d",
+ &KDRpmbTestBanner, r);
+ return r;
+ }
+
+ // check that response or result fields have not been set in response
+ TUint resp = DecodeResponse(iResponse);
+ TUint result = DecodeResult(iResponse);
+
+ if (resp != 0x0006)
+ {
+ Kern::Printf("%S invalid request ID test, unexpected response = %d error",
+ &KDRpmbTestBanner, resp);
+ return KErrGeneral;
+ }
+
+ if (result != 0x0000)
+ {
+ Kern::Printf("%S invalid request ID test, unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+
+ Kern::Printf("%S invalid requeset ID test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+
+
+TInt DRpmbTest::IsKeyProgrammed()
+// send a data write request to the RPMB partition
+// because the request has a blank MAC (not authenticated)
+// the partition returns operation result authentication failure if the key is programmed
+// else the partition returns authentication key not programmed
+ {
+ Kern::Printf("%S data write test", &KDRpmbTestBanner);
+
+ // set up write request packet with blank MAC
+ memset(iRequest, 0, KRpmbOneFramePacketLength);
+ * (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestWriteData;
+
+ // wrap up IO buffers in descriptors to pass across interface
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S data write test, send request error = %d",
+ &KDRpmbTestBanner, r);
+ return r;
+ }
+
+ TUint resp = DecodeResponse(iResponse);
+ TUint result = DecodeResult(iResponse);
+
+ if (resp != KRpmbResponseWriteData)
+ {
+ Kern::Printf("%S data write test, unexpected response = %d error",
+ &KDRpmbTestBanner, resp);
+ return KErrGeneral;
+ }
+
+ if (result == KRpmbResultKeyNotProgrammed)
+ {
+ iKeySet = EFalse;
+ Kern::Printf("%S data write test, key NOT programmed",
+ &KDRpmbTestBanner);
+ }
+ else if (result == KRpmbResultAuthenticationFailure)
+ {
+ iKeySet = ETrue;
+ Kern::Printf("%S data write test, key ALREADY programmed",
+ &KDRpmbTestBanner);
+ }
+ else
+ {
+ Kern::Printf("%S data write test, unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+ Kern::Printf("%S data write test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+
+TInt DRpmbTest::WriteKey()
+ {
+ Kern::Printf("%S write key test", &KDRpmbTestBanner);
+
+ // set up write key request
+ memset(iRequest, 0, KRpmbOneFramePacketLength);
+ * (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestWriteKey;
+ // key = 0x0101010101010101010101010101010101010101010101010101010101010101
+ memset(iRequest+KRpmbKeyOffset,1, KRpmbKeyLength);
+
+ // wrap up IO buffers in descriptors to pass across interface
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S write key test, send request error = %d",
+ &KDRpmbTestBanner, r);
+ return r;
+ }
+
+ TUint resp = DecodeResponse(iResponse);
+ TUint result = DecodeResult(iResponse);
+
+ if (resp != KRpmbResponseWriteKey)
+ {
+ Kern::Printf("%S write key test, unexpected repsponse = %d error",
+ &KDRpmbTestBanner, resp);
+ return KErrGeneral;
+ }
+
+ if (iKeySet)
+ {
+ if (result == KRpmbResultGeneralFailure)
+ {
+ Kern::Printf("%S write key test, key ALREADY written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write key test PASS",
+ &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ else
+ {
+ Kern::Printf("%S write key test, unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+ }
+ else
+ {
+ if(result == KRpmbResultOk)
+ {
+ Kern::Printf("%S write key test, key JUST written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write key test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ else
+ {
+ Kern::Printf("%S write key test unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+ }
+ }
+
+TInt DRpmbTest::ReadWriteCounter()
+ {
+ Kern::Printf("%S read write counter test", &KDRpmbTestBanner);
+
+ // set up read write counter request packet
+ memset(iRequest, 0, KRpmbOneFramePacketLength);
+ * (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadWriteCounter;
+
+ // wrap up IO buffers in descriptors to pass across interface
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+ TInt r = iRpmb.SendAccessRequest(request, response);
+ if (r!=KErrNone)
+ {
+ Kern::Printf("%S read write counter test, send request error = %d",
+ &KDRpmbTestBanner, r);
+ return r;
+ }
+
+ TUint resp = DecodeResponse(iResponse);
+ TUint result = DecodeResult(iResponse);
+ TUint32 counter = DecodeCounter(iResponse);
+
+ if (resp != KRpmbResponseReadWriteCounter)
+ {
+ Kern::Printf("%S read write counter test, unexpected repsponse = %d error",
+ &KDRpmbTestBanner, resp);
+ return KErrGeneral;
+ }
+
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if (result == KRpmbResultOk)
+#else
+ if (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed)
+#endif
+ {
+ Kern::Printf("%S read write counter test write counter = %d",
+ &KDRpmbTestBanner, counter);
+ Kern::Printf("%S read write counter test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ else
+ {
+ Kern::Printf("%S read write counter test, unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+ }
+
+TInt DRpmbTest::ReadData()
+ {
+ Kern::Printf("%S read data test", &KDRpmbTestBanner);
+
+ // set up read request packet
+ memset(iRequest, 0, KRpmbOneFramePacketLength);
+ * (iRequest + KRpmbRequestLsbOffset) = KRpmbRequestReadData;
+
+ // wrap up IO buffers in descriptors to pass across interface
+ TPtr8 request(iRequest,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+ TPtr8 response(iResponse,KRpmbOneFramePacketLength,KRpmbOneFramePacketLength);
+
+ TInt r=iRpmb.SendAccessRequest(request, response);
+ if (r!=KErrNone)
+ {
+ Kern::Printf("%S read data test, send request error = %d",
+ &KDRpmbTestBanner, r);
+ return r;
+ }
+
+ TUint resp = DecodeResponse(iResponse);
+ TUint result = DecodeResult(iResponse);
+
+ if (resp != KRpmbResponseReadData)
+ {
+ Kern::Printf("%S read data test, unexpected repsponse = %d error",
+ &KDRpmbTestBanner, resp);
+ return KErrGeneral;
+ }
+
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if (result == KRpmbResultOk)
+#else
+ if (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed)
+#endif
+ {
+ DisplayReadData(iResponse);
+ Kern::Printf("%S read data test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ else
+ {
+ Kern::Printf("%S read data test, unexpected result = %d error",
+ &KDRpmbTestBanner, result);
+ return KErrGeneral;
+ }
+ }
+
+TUint DRpmbTest::DecodeResponse(TUint8 * aResp)
+ {
+ return (* (aResp + KRpmbResponseLsbOffset) + ((* (aResp + KRpmbResponseMsbOffset)) << 8));
+ }
+
+TUint DRpmbTest::DecodeResult(TUint8 * aResp)
+ {
+ return ((* (aResp + KRpmbResultLsbOffset) + ((* (aResp + KRpmbResultMsbOffset)) << 8))
+ & KRpmbResultCounterExpiredMask);
+ }
+
+TUint32 DRpmbTest::DecodeCounter(TUint8 * aResp)
+ {
+
+ return ((* (aResp + KRpmbCounterByteOneOffset)) + ((* (aResp + KRpmbCounterByteTwoOffset)) << 8)
+ + ((* (aResp + KRpmbCounterByteThreeOffset)) << 16) + ((* (aResp + KRpmbCounterByteFourOffset)) << 24));
+ }
+
+void DRpmbTest::DisplayReadData(TUint8 * aResp)
+ {
+ TUint8 * displayPtr = aResp + KRpmbDataOffset;
+ Kern::Printf("%S data field:", &KDRpmbTestBanner);
+ for (TInt i=0; i<8; i++)
+ {
+ Kern::Printf("%x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x %x%x%x%x",
+ * displayPtr , * (displayPtr + 1), * (displayPtr + 2), * (displayPtr + 3),
+ * (displayPtr + 4), * (displayPtr + 5), * (displayPtr + 6), * (displayPtr + 7),
+ * (displayPtr + 8), * (displayPtr + 9), * (displayPtr + 10), * (displayPtr + 11),
+ * (displayPtr + 12), * (displayPtr + 13), * (displayPtr + 14), * (displayPtr + 15),
+ * (displayPtr + 16), * (displayPtr + 17), * (displayPtr + 18), * (displayPtr + 19),
+ * (displayPtr + 20), * (displayPtr + 21), * (displayPtr + 22), * (displayPtr + 23),
+ * (displayPtr + 24), * (displayPtr + 25), * (displayPtr + 26), * (displayPtr + 27),
+ * (displayPtr + 28), * (displayPtr + 29), * (displayPtr + 30), * (displayPtr + 31));
+ displayPtr +=32;
+ }
+ }
+
+void DRpmbTest::StackCallBack(TAny * aSelf)
+// call back from MMC stack session
+ {
+ // dereference any pointer
+ DRpmbTest& self = *static_cast<DRpmbTest*>(aSelf);
+ // signal semaphore so that calling code progresses
+ Kern::SemaphoreSignal(*(self.iStackSemPtr));
+ }
+
+TInt DRpmbTest::RpmbStackTests()
+// Test code verfies all four access types through a direct connection to the MMC protocol stack
+ {
+ TInt r = SetupForStackTests();
+ if (r == KErrNone)
+ {
+ r = StackBadIndex();
+ }
+ if (r == KErrNone)
+ {
+ r = StackIsKeyProgrammed();
+ }
+// Don't want to write key 'pre production' on a real device as this will lock
+// the system out of the RPMB partition (the key should be preprogrammed as
+// part of the production process so that the system has access to the key -
+// if the key has already been written it can't be written again)
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if (r == KErrNone)
+ {
+ r = StackWriteKey();
+ }
+#endif
+ if (r == KErrNone)
+ {
+ r = StackReadWriteCounter();
+ }
+ if (r == KErrNone)
+ {
+ r = StackReadData();
+ }
+ return r;
+ }
+
+
+TInt DRpmbTest::StackBadIndex()
+// Call MMCGetExtInterface with invalid device id
+// - don't expect params to be returned
+// - expect KErrGeneral return code
+ {
+ Kern::Printf("%S stack device index test", &KDRpmbTestBanner);
+
+ MRpmbInfo* rpmbInterface = NULL;
+ TRpmbDeviceParms parms;
+
+ TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface, this); //this pointer not used in the case of Rpmb
+ if (r!=KErrNone)
+ {
+ Kern::Printf("%S stack device index, MMCGetInterface returned error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+ if (rpmbInterface == NULL)
+ {
+ // unexpected error since MMCGetExtInterface didn't return an error
+ Kern::Printf("%S stack device index, MMCGetInterface returned NULL interface pointer",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ else
+ {
+ r = rpmbInterface->RpmbInfo(1, parms);
+ if (r == KErrNone)
+ {
+ Kern::Printf("%S stack device index test, parmas returned for index 1 error",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+ else if (r != KErrGeneral)
+ {
+ Kern::Printf("%S stack device index test, unexpected rc for index 1 error",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+ }
+ Kern::Printf("%S stack device index test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+}
+
+
+void DRpmbTest::BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2)
+{
+ DRpmbTest* lddPtr = (DRpmbTest*)aPtr;
+ TPBusState busState = (TPBusState) (TInt) a1;
+ TInt busError = (TInt) a2;
+
+ if(aReason == TPBusCallBack::EPBusStateChange
+ && busState == EPBusOn && busError == KErrNone)
+ {
+ Kern::SemaphoreSignal(*(lddPtr->iPowerSemPtr));
+ }
+}
+
+TInt DRpmbTest::SetupForStackTests()
+ {
+ Kern::Printf("%S setup for stack tests", &KDRpmbTestBanner);
+
+ TRpmbDeviceParms parms;
+
+ parms.iCardNumber = 0;
+ parms.iSocketPtr = NULL;
+
+ DMMCStack* stack = NULL;
+ TUint cardNumber = 0;
+ MRpmbInfo* rpmbInterface = NULL;
+
+ TInt r = MMCGetExtInterface(KInterfaceRpmb, (MMCMExtInterface*&) rpmbInterface, this); //this pointer not used in the case of Rpmb
+ if (r!=KErrNone)
+ {
+ Kern::Printf("%S setup for stack tests, MMCGetInterface returned error = %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+ if (rpmbInterface == NULL)
+ {
+ // unexpected error since MMCGetExtInterface didn't return an error
+ return KErrGeneral;
+ }
+
+ else
+ {
+ r = rpmbInterface->RpmbInfo(0, parms);
+ if (r != KErrNone)
+ {
+ // requested index non zero or bseport not configured with RPMB capable MMC device
+ return r;
+ }
+
+ cardNumber = parms.iCardNumber;
+ iSocket = parms.iSocketPtr;
+ if(iSocket == NULL)
+ {
+ Kern::Printf("%S setup for stack tests, socket pointer is NULL",
+ &KDRpmbTestBanner);
+ return KErrNoMemory;
+ }
+
+ // set up to be informed of changes on bus
+ iBusCallBack.iFunction = BusCallBack;
+ iBusCallBack.iPtr=this;
+ iBusCallBack.SetSocket(iSocket->iSocketNumber);
+ iBusCallBack.Add();
+
+ // power up the stack
+ // media drivers don't have to do this at this stage because already done
+ NKern::ThreadEnterCS();
+
+ r = Kern::SemaphoreCreate(iPowerSemPtr,_L("DpmbPowerSem"), 0);
+
+ if (r!=KErrNone)
+ {
+ NKern::ThreadLeaveCS();
+ Kern::Printf("%S sese you below thentup for stack tests, SemaphoreCreate returned %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ r = iSocket->PowerUp();
+
+ if (r!=KErrNone && r!= KErrCompletion)
+ {
+ NKern::ThreadLeaveCS();
+ Kern::Printf("%S setup for stack tests, PowerUp returned %d",
+ &KDRpmbTestBanner, r);
+ return KErrGeneral;
+ }
+
+ if (r == KErrNone)
+ {
+ // wait for socket to power up
+ Kern::SemaphoreWait(*iPowerSemPtr);
+ }
+
+ NKern::ThreadLeaveCS();
+
+ stack = iSocket->Stack(0);
+ if (stack == NULL)
+ {
+ // baseport poorly configured
+ Kern::Printf("%S setup for stack tests, stack pointer is NULL",
+ &KDRpmbTestBanner);
+ return KErrGeneral;
+ }
+ }
+
+ TMMCard* card = stack->CardP(cardNumber);
+
+ if (card == NULL)
+ {
+ // baseport poorly configured
+ Kern::Printf("%S setup for stack tests, card pointer is NULL",
+ &KDRpmbTestBanner);
+ return KErrGeneral;
+ }
+
+ NKern::ThreadEnterCS();
+
+ iSession = stack->AllocSession(iSessionEndCallBack);
+
+ NKern::ThreadLeaveCS();
+
+ if (iSession == NULL)
+ {
+ Kern::Printf("%S setup for stack tests, session pointer is NULL",
+ &KDRpmbTestBanner);
+ return(KErrNoMemory);
+ }
+
+ iSession->SetStack(stack);
+
+ iSession->SetCard(card);
+
+ TUint32 revision = 0;
+
+ // loop until extended csd becomes available in case earlier pause wasn't long enough
+ // this shouldn't need to be done
+ // a reliable method not depending on delays and or polling is required
+ do {
+ stack = iSocket->Stack(0);
+ if (stack)
+ {
+ card = stack->CardP(cardNumber);
+ if (card)
+ {
+ revision = card->ExtendedCSD().ExtendedCSDRev();
+ }
+ }
+ } while (revision==0);
+
+ TUint size = card->ExtendedCSD().RpmbSize();
+
+ if(revision < 5 || size == 0)
+ {
+ Kern::Printf("%S setup for stack test, rpmb partition NOT detected", &KDRpmbTestBanner);
+ return KErrNotSupported;
+ }
+
+ // use memory from stack
+ TInt bufLen, minorBufLen;
+ stack->BufferInfo(iBufPtr, bufLen, minorBufLen);
+ // mmc media driver reserved the first KRpmbOneFramePacketLength bytes of the
+ // PSL buffer to be used for RPMB requests / responses
+ iBufPtr += minorBufLen;
+
+ return KErrNone;
+ }
+
+
+TInt DRpmbTest::StackIsKeyProgrammed()
+// Write Data to block 0 without MACing
+// - expect not MACed error if key set
+// - expect key not prgrammed error if key not programmed
+ {
+
+ Kern::Printf("%S write data stack test", &KDRpmbTestBanner);
+
+ // set up write request packet in stack memory
+ memset(iBufPtr,0,KRpmbOneFramePacketLength);
+ * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestWriteData;
+
+ TInt r = SendToStackAndWait();
+ if (r != KErrNone)
+ {
+ return r;
+ }
+
+ TUint response = DecodeResponse(iBufPtr);
+ TUint result = DecodeResult(iBufPtr);
+
+ if (response == KRpmbResponseWriteData)
+ {
+ if (result == KRpmbResultAuthenticationFailure)
+ {
+ Kern::Printf("%S write data stack test, key IS written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write data stack test PASS", &KDRpmbTestBanner);
+ iKeySet = ETrue;
+ return KErrNone;
+ }
+ else if (result == KRpmbResultKeyNotProgrammed)
+ {
+ Kern::Printf("%S write data stack test, key NOT written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write data stack test PASS",&KDRpmbTestBanner);
+ iKeySet = EFalse;
+ return KErrNone;
+ }
+ }
+ Kern::Printf("%S write data stack test FAILED, response = %d, result = %d",
+ &KDRpmbTestBanner, response, result);
+ return KErrGeneral;
+ }
+
+TInt DRpmbTest::StackWriteKey()
+// Write key
+// - expect no error if key not programmed
+// - expect general error if key already programmed
+ {
+ Kern::Printf("%S write key stack test", &KDRpmbTestBanner);
+
+ // set up write key request packet in stack memory
+ memset(iBufPtr,0,KRpmbOneFramePacketLength);
+ * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestWriteKey;
+
+ TInt r = SendToStackAndWait();
+ if (r != KErrNone)
+ {
+ return r;
+ }
+
+ TUint response = DecodeResponse(iBufPtr);
+ TUint result = DecodeResult(iBufPtr);
+
+ if (response == KRpmbResponseWriteKey)
+ {
+ if (iKeySet && result == KRpmbResultGeneralFailure)
+ {
+ Kern::Printf("%S write key stack test, key ALREADY written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write key stack test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ else if (!iKeySet && result == KRpmbResultOk)
+ {
+ Kern::Printf("%S write key stack test, key JUST written",
+ &KDRpmbTestBanner);
+ Kern::Printf("%S write key stack test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ }
+ Kern::Printf("%S write key stack test FAILED, response = %d, result = %d",
+ &KDRpmbTestBanner, response, result);
+ return KErrGeneral;
+ }
+
+TInt DRpmbTest::StackReadWriteCounter()
+// Read Data Counter
+// - expect no error
+ {
+ Kern::Printf("%S read write counter stack test", &KDRpmbTestBanner);
+
+ // set up write key request packet in stack memory
+ memset(iBufPtr,0,KRpmbOneFramePacketLength);
+ * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadWriteCounter;
+
+ TInt r = SendToStackAndWait();
+ if (r != KErrNone)
+ {
+ return r;
+ }
+
+ TUint response = DecodeResponse(iBufPtr);
+ TUint result = DecodeResult(iBufPtr);
+ TUint32 counter = DecodeCounter(iBufPtr);
+
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if ((response == KRpmbResponseReadWriteCounter) && (result == KRpmbResultOk))
+#else
+ if ((response == KRpmbResponseReadWriteCounter)
+ && (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed))
+#endif
+ {
+ Kern::Printf("%S read write counter stack test, counter = %d",
+ &KDRpmbTestBanner, counter);
+ Kern::Printf("%S read write counter stack test PASS",
+ &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ Kern::Printf("%S read write counrter stack test FAILED, response = %d, result = %d",
+ &KDRpmbTestBanner, response, result);
+ return KErrGeneral;
+ }
+
+
+TInt DRpmbTest::StackReadData()
+// Read Data from block 0
+// - expect no error
+ {
+ Kern::Printf("%S read data stack test", &KDRpmbTestBanner);
+
+ // set up write key request packet in stack memory
+ memset(iBufPtr,0,KRpmbOneFramePacketLength);
+ * (iBufPtr + KRpmbRequestLsbOffset) = KRpmbRequestReadData;
+
+ TInt r = SendToStackAndWait();
+ if (r != KErrNone)
+ {
+ return r;
+ }
+
+ TUint response = DecodeResponse(iBufPtr);
+ TUint result = DecodeResult(iBufPtr);
+
+#ifdef RPMBTESTS_TRY_TO_WRITE_KEY
+ if ((response == KRpmbResponseReadData) && (result == KRpmbResultOk))
+#else
+ if ((response == KRpmbResponseReadData)
+ && (result == KRpmbResultOk || result == KRpmbResultKeyNotProgrammed))
+#endif
+ {
+ DisplayReadData(iBufPtr);
+ Kern::Printf("%S read data stack test PASS", &KDRpmbTestBanner);
+ return KErrNone;
+ }
+ Kern::Printf("%S read data stack test FAILED, response = %d, result = %d",
+ &KDRpmbTestBanner, response, result);
+ return KErrGeneral;
+ }
+
+TInt DRpmbTest::SendToStackAndWait()
+ {
+// comment out to get timings with RPMB -> RPMB switches in place of User
+// Area -> RPMB switces
+#define RPMBSTACKTEST_FIRST_SWITCH_TO_USER_AREA
+#ifdef RPMBSTACKTEST_FIRST_SWITCH_TO_USER_AREA
+ // in normal operation it may be necessary to switch to RPMB partition
+ // prior to access
+ // so force the switch to occur by pre switching to the user area
+ iSession->SetPartition(TExtendedCSD::ESelectUserArea);
+#endif
+
+ TInt start, postswitch, end;
+
+ start = NKern::TickCount();
+
+ // lock stack
+ TInt r = iSocket->InCritical();
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S DRpmbTest::SendToStackAndWait, error=%d",
+ &KDRpmbTestBanner, r);
+ iSocket->EndInCritical();
+ return KErrGeneral;
+ }
+
+ // switch to RPMB partition
+ iSession->SetPartition(TExtendedCSD::ESelectRPMB);
+
+ postswitch = NKern::TickCount();
+
+ // set up for write exchange
+ iSession->ResetCommandStack();
+ iSession->FillCommandArgs(0, KRpmbOneFramePacketLength, iBufPtr, KRpmbOneFramePacketLength);
+ iSession->iSessionID = ECIMRpmbAccess;
+ iSession->Engage();
+
+ // wait for stack call to complete
+ r = Kern::SemaphoreWait(*iStackSemPtr);
+
+ end = NKern::TickCount();
+
+ Kern::Printf("%S switch to RPMB took %d %d uS timer ticks",
+ &KDRpmbTestBanner, start - postswitch, NKern::TickPeriod());
+ Kern::Printf("%S RPMB ECIMRpmbAccess took %d %d uS timer ticks",
+ &KDRpmbTestBanner, end - postswitch, NKern::TickPeriod());
+
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S DRpmbTest::SendToStackAndWait, SemaphoreWait return code = %d",
+ &KDRpmbTestBanner, r);
+ iSocket->EndInCritical();
+ return KErrGeneral;
+ }
+
+ // check stack epoc return code
+ r = iSession->EpocErrorCode();
+ if (r != KErrNone)
+ {
+ Kern::Printf("%S DRpmbTest::stack epoc return code = %d",
+ &KDRpmbTestBanner, r);
+ iSocket->EndInCritical();
+ return KErrGeneral;
+ }
+
+ // unlock stack
+ iSocket->EndInCritical();
+
+ return KErrNone;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 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:
+// e32test/rpmb/rpmb.h
+//
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#include <kernel/kern_priv.h>
+#include <drivers/rpmbdevice.h>
+#include <drivers/mmc.h>
+
+// banner for reporting progress of these tests
+_LIT(KDRpmbTestBanner,"RPMB TEST DRIVER: ");
+
+// RPMB test driver factory class
+class DRpmbTestFactory : public DLogicalDevice
+ {
+public:
+ DRpmbTestFactory();
+ ~DRpmbTestFactory();
+ virtual TInt Install();
+ virtual void GetCaps(TDes8& aDes) const;
+ virtual TInt Create(DLogicalChannelBase*& aChannel);
+ };
+
+// RPMB test driver request handling class
+class DRpmbTest : public DLogicalChannelBase
+ {
+public:
+ DRpmbTest();
+ virtual ~DRpmbTest();
+ TInt DRpmbDeviceTests();
+ TInt RpmbStackTests();
+protected:
+ TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+ TInt Request(TInt aFunction, TAny* a1, TAny* a2);
+private:
+ TInt SendAccessRequestNotOpen();
+ TInt OpenWithBadIndex();
+ TInt MultipleOpen();
+ TInt SendAccessRequestBadParms();
+ TInt InvalidRequestId();
+ TInt IsKeyProgrammed();
+ TInt WriteKey();
+ TInt ReadWriteCounter();
+ TInt ReadData();
+ TUint DecodeResponse(TUint8 * aResp);
+ TUint DecodeResult(TUint8 * aResp);
+ TUint32 DecodeCounter(TUint8 * aResp);
+ void DisplayReadData(TUint8 * aResp);
+ static void BusCallBack(TAny* aPtr, TInt aReason, TAny* a1, TAny* a2);
+ static void StackCallBack(TAny * aSelf);
+ TInt StackBadIndex();
+ TInt SetupForStackTests();
+ TInt StackIsKeyProgrammed();
+ TInt StackWriteKey();
+ TInt StackReadWriteCounter();
+ TInt StackReadData();
+ TInt SendToStackAndWait();
+private:
+ DRpmbDevice iRpmb;
+ DRpmbDevice iRpmbSecondInstance;
+ TUint8 * iRequest;
+ TUint8 * iResponse;
+ TBool iKeySet;
+ TUint8* iBufPtr;
+ DSemaphore * iStackSemPtr;
+ DSemaphore * iPowerSemPtr;
+ TPBusCallBack iBusCallBack;
+ TMMCCallBack iSessionEndCallBack;
+ DMMCSocket* iSocket;
+ DMMCSession* iSession;
+ };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/driver/d_rpmb.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,43 @@
+/// Copyright (c) 2010 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:
+// e32test/group/d_rpmb.mmp
+//
+//
+
+/**
+ @file
+*/
+
+#include "kernel/kern_ext.mmh"
+
+target d_rpmb.ldd
+targettype ldd
+sourcepath ./
+source d_rpmb.cpp
+
+library rpmbext.lib
+
+library epbusmmc.lib
+
+epocallowdlldata
+
+vendorid 0x70000001
+
+start wins
+win32_headers
+end
+
+capability all
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/rpmbtestautoexec.bat Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,17 @@
+rem
+rem Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+rem All rights reserved.
+rem This component and the accompanying materials are made available
+rem under the terms of the License "Eclipse Public License v1.0"
+rem which accompanies this distribution, and is available
+rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+rem
+rem Initial Contributors:
+rem Nokia Corporation - initial contribution.
+rem
+rem Contributors:
+rem
+rem Description:
+rem
+
+t_rpmb
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,58 @@
+
+// Copyright (c) 2010 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:
+// e32test/rpmb/t_rpmb.cpp
+// LDD for testing RPMB kernel extension
+//
+//
+
+/**
+ @file
+ @internalComponent
+ @prototype
+*/
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include "t_rpmb.h"
+
+RTest test(_L("t_rpmb"));
+RTestRpmb RpmbTestDeviceDriver;
+
+/******************************************************************************
+ * Main
+ ******************************************************************************/
+TInt E32Main()
+ {
+#if !defined(__WINS__)
+ test.Title();
+ test.Start(_L("Opening device driver"));
+ TInt r;
+ r = User::LoadLogicalDevice(KRpmbTestLddName);
+ test_Value(r,r==KErrNone||r==KErrAlreadyExists);
+ r = RpmbTestDeviceDriver.Open();
+ test_KErrNone(r);
+ test.Next(_L("Execute RPMB tests"));
+ r = RpmbTestDeviceDriver.RunTests();
+ test_KErrNone(r);
+ RpmbTestDeviceDriver.Close();
+ r = User::FreeLogicalDevice(KRpmbTestLddName);
+ test_KErrNone(r);
+ test.End();
+#else
+test.Printf(_L("This test does not run on emulator. \n"));
+#endif
+ return 0;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.h Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,43 @@
+// Copyright (c) 2010 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:
+// e32test/rpmb/t_rpmb.h
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @prototype
+*/
+
+// name of kernel side RPMB test driver
+_LIT(KRpmbTestLddName,"d_rpmb");
+
+// user side client object for accessing kernel side RPMB test driver
+class RTestRpmb : public RBusLogicalChannel
+ {
+public:
+ enum TControl
+ {
+ ERunTests=0,
+ };
+#ifndef __KERNEL_MODE__
+// these public methods are only accessed from the user side
+public:
+ inline TInt Open()
+ { return DoCreate(KRpmbTestLddName,TVersion(),KNullUnit,NULL,NULL); }
+ inline TInt RunTests()
+ { return DoControl(ERunTests); }
+#endif // __KERNEL_MODE__
+ };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rpmb/t_rpmb.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,35 @@
+/// Copyright (c) 2010 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:
+// e32test/group/t_rpmb.mmp
+//
+//
+
+/**
+ @file
+*/
+
+target t_rpmb.exe
+targettype exe
+sourcepath ../rpmb
+source t_rpmb.cpp
+
+library euser.lib
+userinclude ../rpmb
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+vendorid 0x70000001
+
+capability none
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/bench/t_trimbm.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,875 @@
+// Copyright (c) 1996-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:
+// f32test/bench/t_fsysbm.cpp
+//
+//
+
+#define __E32TEST_EXTENSION__
+
+#include <f32file.h>
+#include <e32test.h>
+#include <e32hal.h>
+#include <hal.h>
+#include <e32math.h>
+#include <e32ldr.h>
+#include <e32ldr_private.h>
+#include "t_server.h"
+#include "../../e32test/mmu/d_sharedchunk.h"
+#include "../../e32utils/pccd/d_mmcif.h"
+
+#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES // test using a greater number of buffer sizes
+
+RTest test(_L("eMMC 4.4 TRIM Benchmark"));
+
+static const TUint K1K = 1024; // 1K
+static const TUint K1M = K1K * K1K ; // 1M
+static const TUint K2M = 2 * K1M; // 2M
+
+
+#if defined(__WINS__)
+static TInt KMaxFileSize = 256 * K1K; // 256K
+#else
+static TInt KMaxFileSize = K2M; // 2M
+#endif
+
+const TTimeIntervalMicroSeconds32 KFloatingPointTestTime = 10000000; // 10 seconds
+
+static TPtr8 DataBuf(NULL, KMaxFileSize,KMaxFileSize);
+
+static RSharedChunkLdd Ldd;
+static RChunk TheChunk;
+
+GLDEF_D RFs TheFs;
+GLDEF_D TFileName gSessionPath;
+GLDEF_D TChar gDriveToTest;
+
+static RMmcCntrlIf iDriver;
+static TInt iStack = 0;
+static TInt iCard = 0;
+static TBool iDriverOpen = EFalse;
+
+enum TPanic {ECreatingConsole,ELoaderCheck,ELoadingMmcDriver,EStartingMmcDriver};
+
+LOCAL_C void Panic(TPanic aPanic)
+//
+// Panic
+//
+ {
+ User::Panic(_L("MMCTEST"),aPanic);
+ }
+
+
+static RFile File;
+
+static TInt gFastCounterFreq;
+
+const TUint KMMCExtendedCSDLength=512;
+class TExtendedCSD
+ {
+public:
+ enum TExtCSDAccessBits {ECmdSet, ESetBits, EClearBits, EWriteByte};
+ enum TExtCSDModesFieldIndex
+ {
+ ECmdSetIndex = 191,
+ ECmdSetRevIndex = 189,
+ EPowerClassIndex = 187,
+ EHighSpeedInterfaceTimingIndex = 185,
+ EBusWidthModeIndex = 183
+ };
+ enum TExtCSDBusWidths
+ {
+ EExtCsdBusWidth1 = 0x00,
+ EExtCsdBusWidth4 = 0x01,
+ EExtCsdBusWidth8 = 0x02
+ };
+ enum TCardTypes
+ {
+ EHighSpeedCard26Mhz = 0x01,
+ EHighSpeedCard52Mhz = 0x02
+ };
+public:
+ inline TExtendedCSD(); // Default constructor
+ inline TExtendedCSD(const TUint8*);
+ inline TExtendedCSD& operator=(const TExtendedCSD&);
+ inline TExtendedCSD& operator=(const TUint8*);
+ inline TUint8 At(TUint anIndex) const; // Byte from CSD at anIndex
+public:
+ inline TUint SupportedCmdSet() const;
+ inline TUint MinPerfWrite8Bit52Mhz() const;
+ inline TUint MinPerfRead8Bit52Mhz() const;
+ inline TUint MinPerfWrite8Bit26Mhz_4Bit52Mhz() const;
+ inline TUint MinPerfRead8Bit26Mhz_4Bit52Mhz() const;
+ inline TUint MinPerfWrite4Bit26Mhz() const;
+ inline TUint MinPerfRead4Bit26Mhz() const;
+ inline TUint PowerClass26Mhz360V() const;
+ inline TUint PowerClass52Mhz360V() const;
+ inline TUint PowerClass26Mhz195V() const;
+ inline TUint PowerClass52Mhz195V() const;
+ inline TUint CardType() const;
+ inline TUint CSDStructureVer() const;
+ inline TUint ExtendedCSDRev() const;
+ inline TUint CmdSet() const;
+ inline TUint CmdSetRev() const;
+ inline TUint PowerClass() const;
+ inline TUint HighSpeedTiming() const;
+ inline TUint BusWidth() const;
+
+ inline TUint TrimMultiplier() const;
+ inline TUint SecureFeatureSupport() const;
+ inline TUint SecureEraseMultiplier() const;
+ inline TUint SecureTrimMultiplier() const;
+
+private:
+ /**< @internalComponent little endian 512 byte field representing extended CSD */
+ TUint8 iData[KMMCExtendedCSDLength];
+ };
+
+inline TExtendedCSD::TExtendedCSD() // Default constructor
+ {}
+inline TExtendedCSD::TExtendedCSD(const TUint8* aPtr)
+ {memcpy(&iData[0], aPtr, KMMCExtendedCSDLength);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TExtendedCSD& aCSD)
+ {memcpy(&iData[0], &aCSD.iData[0], KMMCExtendedCSDLength); return(*this);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TUint8* aPtr)
+ {memcpy(&iData[0], aPtr, KMMCExtendedCSDLength); return(*this);}
+// field accessors.
+// "Properties Segment" of Extended CSD - i.e. read-only fields
+inline TUint TExtendedCSD::SupportedCmdSet() const {return iData[504];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit52Mhz() const {return iData[210];}
+inline TUint TExtendedCSD::MinPerfRead8Bit52Mhz() const {return iData[209];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit26Mhz_4Bit52Mhz() const {return iData[208];}
+inline TUint TExtendedCSD::MinPerfRead8Bit26Mhz_4Bit52Mhz() const {return iData[207];}
+inline TUint TExtendedCSD::MinPerfWrite4Bit26Mhz() const {return iData[206];}
+inline TUint TExtendedCSD::MinPerfRead4Bit26Mhz() const {return iData[205];}
+inline TUint TExtendedCSD::PowerClass26Mhz360V() const {return iData[203];}
+inline TUint TExtendedCSD::PowerClass52Mhz360V() const {return iData[202];}
+inline TUint TExtendedCSD::PowerClass26Mhz195V() const {return iData[201];}
+inline TUint TExtendedCSD::PowerClass52Mhz195V() const {return iData[200];}
+inline TUint TExtendedCSD::CardType() const {return iData[196];}
+inline TUint TExtendedCSD::CSDStructureVer() const {return iData[194];}
+inline TUint TExtendedCSD::ExtendedCSDRev() const {return iData[192];}
+
+inline TUint TExtendedCSD::TrimMultiplier() const {return iData[232]; }
+inline TUint TExtendedCSD::SecureFeatureSupport() const {return iData[231]; }
+inline TUint TExtendedCSD::SecureEraseMultiplier() const {return iData[230]; }
+inline TUint TExtendedCSD::SecureTrimMultiplier() const {return iData[229]; }
+
+
+// "Modes Segment" of Extended CSD - i.e. modifiable fields
+inline TUint TExtendedCSD::CmdSet() const {return iData[191];}
+inline TUint TExtendedCSD::CmdSetRev() const {return iData[189];}
+inline TUint TExtendedCSD::PowerClass() const {return iData[187];}
+inline TUint TExtendedCSD::HighSpeedTiming() const {return iData[185];}
+typedef TPckg<TExtendedCSD> TExtendedCSDPckg;
+
+static TExtendedCSD extCSD;
+
+GLDEF_C TInt CurrentDrive()
+//
+// Return the current drive number
+//
+ {
+
+ TInt driveNum;
+ TInt r=TheFs.CharToDrive(gSessionPath[0],driveNum);
+ test_KErrNone(r);
+ return(driveNum);
+ }
+
+GLDEF_C void Format(TInt aDrive)
+//
+// Format current drive
+//
+ {
+
+ TUint initTicks = User::FastCounter();
+ TUint finalTicks = 0;
+
+ TBuf<4> driveBuf=_L("?:\\");
+ driveBuf[0]=(TText)(aDrive+'A');
+ RFormat format;
+ TInt count;
+
+ TInt r=format.Open(TheFs,driveBuf, EFullFormat,count); // EQuickFormat
+ test_KErrNone(r);
+ while(count)
+ {
+ TInt r=format.Next(count);
+ test_KErrNone(r);
+ }
+ format.Close();
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to format %d ms)\n"), timeTakenInMs);
+ }
+
+
+
+static TInt getExtendedCSD()
+ {
+
+ if (!iDriverOpen)
+ return(KErrNotSupported);
+
+
+ // Power the stack down & up to make sure the CardInfo is up to date
+ iDriver.Reset();
+ User::After(1000);
+ iDriver.PwrDownStack();
+ User::After(1000);
+ TRequestStatus status;
+ iDriver.PwrUpAndInitStack(status);
+ User::WaitForRequest(status);
+ TInt err;
+ if ((err=status.Int())!=KErrNone)
+ {
+ test.Printf(_L("Error Powering Stack"),err);
+ return(err);
+ }
+ iDriver.SelectCard(iCard);
+
+ // Get the CSD first to check whether the ExtCSD is supported
+ TMmcCardInfo ci;
+ if ((err = iDriver.CardInfo(ci))!=KErrNone)
+ {
+ test.Printf(_L("Error getting card info"),err);
+ return(err);
+ }
+ //test.Printf(_L("CSD Spec version: %u\n"), ci.iSpecVers);
+
+ if (ci.iSpecVers < 4)
+ {
+ test.Printf(_L("Error: Extended CSD not supported\n"));
+ return KErrNotSupported;
+ }
+
+ TExtendedCSDPckg extCSDPckg(extCSD);
+
+ iDriver.ReadExtCSD(status, extCSDPckg);
+
+ User::WaitForRequest(status);
+
+ if (status.Int() != KErrNone)
+ {
+ test.Printf(_L("Error getting Extended CSD\n"));
+ return(KErrGeneral);
+ }
+ return err;
+ }
+
+
+static TUint GetSecEraseMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.SecureEraseMultiplier();
+
+ return retVal;
+ }
+
+static TUint GetSecTrimMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.SecureTrimMultiplier();
+
+ return retVal;
+ }
+
+static TUint GetTrimMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.TrimMultiplier();
+
+ return retVal;
+ }
+
+static TInt64 DiskSize(TInt aDrive)
+//
+//
+//
+ {
+ TVolumeInfo v;
+ TInt r=TheFs.Volume(v,aDrive);
+ test_KErrNone(r);
+ return(v.iSize);
+ }
+
+static TInt CalcEntries(TInt64 aDiskSize, TUint& aEntrySize)
+ {
+
+ aEntrySize = KMaxFileSize;
+ TInt numFiles = (TInt)(aDiskSize / aEntrySize);
+
+ while ( numFiles > 1000 )
+ {
+ aEntrySize = aEntrySize << 2 ;
+ numFiles = (TUint)(aDiskSize / aEntrySize);
+ }
+ return numFiles;
+
+ }
+
+static void WriteFull(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ RFile f;
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+ TBuf8<8> WriteData =_L8("Wibbleuy");
+
+ r=TheFs.MkDirAll(gSessionPath);
+
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Create %d entries\n"),numFiles);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; ++i)
+ {
+
+ test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName= gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ r=f.Replace(TheFs,baseName,EFileWrite);
+ test_KErrNone(r);
+ r = f.SetSize(entrySize);
+ if( r == KErrDiskFull)
+ {
+ numFiles = i;
+ break;
+ }
+ test_Value(r, r == KErrNone || r==KErrDiskFull);
+ r=f.Write((entrySize-30),WriteData);
+ test_KErrNone(r);
+ f.Flush();
+ f.Close();
+ }
+
+ test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ test.Printf(_L("Test all entries have been created successfully\n"));
+ TBuf8<8> ReadData;
+ TInt Size=0;
+ for (TInt j=0; j < numFiles; j++)
+ {
+
+ test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(j);
+
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ test_Value(r, r == KErrNotFound && j==numFiles);
+ return;
+ }
+ ReadData.FillZ();
+ r=f.Read((entrySize-30),ReadData);
+ test_KErrNone(r);
+ test(f.Size(Size)==KErrNone);
+ test(entrySize == (TUint)Size);
+ test(ReadData==WriteData);
+ f.Close();
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles );
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+static void ReWriteHalf(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ RFile f;
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+ TBuf8<8> WriteData =_L8("Wibbleuy");
+
+ r=TheFs.MkDirAll(gSessionPath);
+
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Create %d entries\n"),numFiles/2);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; i += 2)
+ {
+
+ test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName= gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ r=f.Replace(TheFs,baseName,EFileWrite);
+ test_KErrNone(r);
+ r = f.SetSize(entrySize);
+ if( r == KErrDiskFull)
+ {
+ numFiles = i;
+ break;
+ }
+ test_Value(r, r == KErrNone || r==KErrDiskFull);
+ r=f.Write((entrySize-30),WriteData);
+ test_KErrNone(r);
+ f.Flush();
+ f.Close();
+ }
+
+ test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ test.Printf(_L("Test all entries have been created successfully\n"));
+ TBuf8<8> ReadData;
+ TInt Size=0;
+ for (TInt j=0; j < numFiles; j += 2)
+ {
+
+ test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(j);
+
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ test_Value(r, r == KErrNotFound && j==numFiles);
+ return;
+ }
+ ReadData.FillZ();
+ r=f.Read((entrySize-30),ReadData);
+ test_KErrNone(r);
+ test(f.Size(Size)==KErrNone);
+ test(entrySize == (TUint)Size);
+ test(ReadData==WriteData);
+ f.Close();
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2 );
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+
+
+static void DeleteAll(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Delete %d entries\n"),numFiles);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ initTicks = User::FastCounter();
+
+ for( TInt i = 2; i < numFiles; ++i)
+ {
+ test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ TInt r=TheFs.Delete(baseName);
+ test_Value(r, r == KErrNotFound || r == KErrNone);
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles);
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+static void DeleteHalf(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Delete %d entries\n"),numFiles/2);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; i +=2)
+ {
+ test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ TInt r=TheFs.Delete(baseName);
+ test_Value(r, r == KErrNotFound || r == KErrNone);
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2);
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+
+static void WaitUntilTrimDone()
+ {
+
+ TUint initTicks = User::FastCounter();
+ TUint finalTicks = 0;
+
+#define READ_TO_KEEP_CARD_ON
+#ifdef READ_TO_KEEP_CARD_ON
+
+ const TInt readSize = 4096;
+ const TInt timeToRead = 30;
+
+ test.Printf(_L("Read a file for %d sec to keep card power on\n"), timeToRead );
+ TBuf8<4096> ReadData;
+
+ RTimer timer;
+ timer.CreateLocal();
+ TRequestStatus reqStat;
+
+ //test.Printf(_L("Timer started.\n"));
+
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE1"));
+
+ RFile f;
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ return;
+ }
+ TInt alreadyRead = 0;
+ TInt fileSize;
+ test(f.Size(fileSize)==KErrNone);
+
+ //test.Printf(_L("File size:%d.\n"), fileSize);
+
+ timer.After(reqStat, timeToRead*1000000); // After 30 secs
+
+ while( reqStat==KRequestPending )
+ {
+
+ test.Printf(_L("Read pos:%d\r"), alreadyRead );
+ ReadData.FillZ();
+ r=f.Read(readSize,ReadData);
+
+ test_KErrNone(r);
+ alreadyRead += readSize;
+ if( alreadyRead == fileSize)
+ {
+ alreadyRead = 0;
+ f.Seek(ESeekStart, alreadyRead);
+ }
+ User::After(1000); // 1 ms
+ }
+
+ timer.Close();
+
+ f.Close();
+
+ test.Printf(_L("\n"));
+
+#else
+
+ TInt trimMult = GetTrimMultValue(); // Get TRIM_MULT value from eMMC Extended CSD
+ test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+ while( trimMult-- > 0 )
+ {
+ // Wait for a while
+ User::After(300000); // TRIM Timeout = 300ms x TRIM_MULT
+ test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+ TInt trim = GetTrimMultValue();
+ }
+
+#endif
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to TRIM done = %d ms\n"), timeTakenInMs);
+ }
+
+
+
+void doExit()
+ {
+ iDriver.Close();
+
+ User::FreeLogicalDevice(_L("MmcIf"));
+
+ test.End();
+ test.Close();
+
+ }
+
+GLDEF_C void CallTestsL(void)
+//
+// Call all tests
+//
+ {
+
+ test.Next(gSessionPath);
+
+ TInt err;
+ err=User::LoadLogicalDevice(_L("D_MMCIF"));
+ __ASSERT_ALWAYS((err==KErrNone||err==KErrAlreadyExists),Panic(ELoadingMmcDriver));
+ test.Printf(_L("MMCIF driver loaded\n"));
+
+
+ iDriver.Close();
+ TInt r=iDriver.Open(iStack,iDriver.VersionRequired());
+ iDriverOpen=(r==KErrNone)?(TBool)ETrue:(TBool)EFalse;
+ test.Printf(_L("iDriverOpen %d\n"), iDriverOpen);
+ if( !iDriverOpen )
+ {
+ doExit();
+ return;
+ }
+
+ test.Next(_L("Get extended CSD"));
+ r = getExtendedCSD();
+
+ if( r != KErrNone )
+ {
+ test.Next(_L("Extended CSD doesn't exists. Exit."));
+ doExit();
+ return;
+ }
+
+ if( extCSD.ExtendedCSDRev() < 5 )
+ {
+ test.Next(_L("TRIM feature doesn't exists. Exit!"));
+ }
+
+
+ r = HAL::Get(HAL::EFastCounterFrequency, gFastCounterFreq);
+ test_KErrNone(r);
+ test.Printf(_L("HAL::EFastCounterFrequency %d\n"), gFastCounterFreq);
+
+
+ TInt currentDrive = CurrentDrive();
+
+ // 1. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 2. Set TRIM off
+ //test.Next(_L("Set TRIM off"));
+
+
+ // 3. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 4. Delete all files and measure elapsed time
+ test.Next(_L("Delete all files"));
+ DeleteAll(currentDrive);
+
+ // 5. Rewrite all (or a set of) files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 6. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 7. Set TRIM on
+ //test.Next(_L("Set TRIM on"));
+
+ // 8. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 9. Delete all files and measure elapsed time
+ test.Next(_L("Delete all files"));
+ DeleteAll(currentDrive);
+
+ // 10. Wait for a while (give time to eMMC to do its TRIM job)
+ test.Next(_L("Wait for TRIM done"));
+ WaitUntilTrimDone();
+
+ // 11. Rewrite all (or same set of) files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 12. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 13. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 14. Delete half of files and measure elapsed time
+ test.Next(_L("Delete half of files"));
+ DeleteHalf(currentDrive);
+
+ // 15. Re-write half of files and measure elapsed time
+ test.Next(_L("Re-write half"));
+ ReWriteHalf(currentDrive);
+
+
+ // 16. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 17. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 18. Delete half of files and measure elapsed time
+ test.Next(_L("Delete half of files"));
+ DeleteHalf(currentDrive);
+
+ // 19. Wait for a while (give time to eMMC to do its TRIM job)
+ test.Next(_L("Wait for TRIM done"));
+ WaitUntilTrimDone();
+
+ // 20. Re-write half of files and measure elapsed time
+ test.Next(_L("Re-write half"));
+ ReWriteHalf(currentDrive);
+
+ // 21. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ doExit();
+
+ return;
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ TInt r=TheFs.Connect();
+ test_KErrNone(r);
+
+ test.Title();
+ test.Start(_L("Start Benchmarking ..."));
+
+ TInt theDrive;
+ gDriveToTest='E';
+ r=TheFs.CharToDrive(gDriveToTest,theDrive);
+ test_KErrNone(r);
+
+ gSessionPath=_L("?:\\TRIMTEST\\");
+ TChar driveLetter;
+ r=TheFs.DriveToChar(theDrive,driveLetter);
+ test_KErrNone(r);
+ gSessionPath[0]=(TText)driveLetter;
+ r=TheFs.SetSessionPath(gSessionPath);
+ test_KErrNone(r);
+
+ r=TheFs.MkDirAll(gSessionPath);
+ if(r == KErrCorrupt)
+ {
+ test.Printf(_L("Attempting to create directory \'%S\' failed, KErrCorrupt\n"), &gSessionPath);
+ test.Printf(_L("This could be caused by a previous failing test, or a test media defect\n"));
+ test.Printf(_L("Formatting drive, retrying MkDirall\nShould subsequent tests fail with KErrCorrupt (%d) as well, replace test medium !\n"),
+ r);
+ Format(theDrive);
+ r=TheFs.MkDirAll(gSessionPath);
+ test_KErrNone(r);
+ }
+ else if (r == KErrNotReady)
+ {
+ TDriveInfo d;
+ r=TheFs.Drive(d, theDrive);
+ test_KErrNone(r);
+ if (d.iType == EMediaNotPresent)
+ test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)driveLetter);
+ else
+ test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)d.iType, (TUint)driveLetter);
+ }
+ test_Value(r, r == KErrNone || r == KErrAlreadyExists);
+
+
+ CallTestsL();
+
+ TheFs.Close();
+
+ return(KErrNone);
+ }
--- a/kerneltest/f32test/group/bld.inf Mon Oct 11 17:54:41 2010 +0100
+++ b/kerneltest/f32test/group/bld.inf Mon Oct 11 19:11:06 2010 +0100
@@ -55,6 +55,9 @@
t_fsrvbm support
t_fsysbm support
+
+t_trimbm manual
+
t_whet support
#ifdef ARMCC
t_whetvfp support
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/group/t_trimbm.mmp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,35 @@
+// Copyright (c) 1997-2010 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:
+// f32test/group/t_trimbm.mmp
+//
+//
+
+TARGET t_trimbm.exe
+TARGETTYPE EXE
+SOURCEPATH ../bench
+SOURCE t_trimbm.cpp
+SOURCEPATH ../server
+SOURCEPATH ../fileutils/src
+SOURCE t_chlffs.cpp
+
+LIBRARY euser.lib efsrv.lib hal.lib
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+USERINCLUDE ../server
+USERINCLUDE ../fileutils/inc
+
+EPOCHEAPSIZE 0x1000 0x02000000
+CAPABILITY TCB DISKADMIN ALLFILES
+VENDORID 0x70000001
+
+SMPSAFE