kernel/eka/drivers/medmmc/bgahsmmcptn.cpp
changeset 300 1d28c8722707
parent 287 ddfd5aa0d58f
equal deleted inserted replaced
293:0659d0e1a03c 300:1d28c8722707
    32 
    32 
    33 public:
    33 public:
    34 	virtual TInt Initialise(DMediaDriver* aDriver);
    34 	virtual TInt Initialise(DMediaDriver* aDriver);
    35 	virtual TInt PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack);
    35 	virtual TInt PartitionInfo(TPartitionInfo& anInfo, const TMMCCallBack& aCallBack);
    36 	virtual TInt PartitionCaps(TLocDrv& aDrive, TDes8& aInfo);
    36 	virtual TInt PartitionCaps(TLocDrv& aDrive, TDes8& aInfo);
    37 
    37 	TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
       
    38 	
    38 protected:
    39 protected:
    39 	void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
    40 	void SetPartitionEntry(TPartitionEntry* aEntry, TUint aFirstSector, TUint aNumSectors);
    40 
    41 
    41 private:
    42 private:
    42 	virtual TInt ReadPartition(TUint32 aPtOffset);
    43 	virtual TInt ReadPartition(TUint32 aPtOffset);
       
    44 	virtual TInt ReadPartition(TUint32 aPtOffset, TUint aNumBlocks);
    43 	static void SessionEndCallBack(TAny* aSelf);
    45 	static void SessionEndCallBack(TAny* aSelf);
    44 	void DoSessionEndCallBack();
    46 	void DoSessionEndCallBack();
    45 	virtual TInt DecodePartitionInfo();
    47 	TInt DecodeTOCPartitionInfo();
       
    48 	TInt DecodeBB5PartitionInfo();
       
    49 	TInt CheckPartitionBoundaries(TInt aStart, TInt aEnd);
    46 	TInt GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize);
    50 	TInt GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize);
    47 	TInt GetPartitionOffset(TUint32& aPtOffset);
    51 	TInt GetPartitionOffset(TUint32& aPtOffset);
    48 	TInt SelectNextPartition();
    52 	TInt SelectNextPartition();
    49 
    53 	TInt ReadTOCVersionInfo(TUint32& aOffset);
       
    54 	void DecodeVersionInfo();
       
    55 
       
    56 private:	
       
    57 	enum TMediaRequest
       
    58 	    {
       
    59         EIdle                    = 0x00,
       
    60         EDecodeBB5PartitionInfo  = 0x01,
       
    61         EDecodeTOCPartitionInfo  = 0x02,        
       
    62         EReadImageVersionInfo    = 0x03,	    
       
    63 	    };
       
    64 	
    50 protected:
    65 protected:
       
    66 		
    51 	DMediaDriver*	iDriver;
    67 	DMediaDriver*	iDriver;
    52 	TPartitionInfo* iPartitionInfo;
    68 	TPartitionInfo* iPartitionInfo;
    53 	TMMCCallBack	iSessionEndCallBack;
    69 	TMMCCallBack	iSessionEndCallBack;
    54 	TMMCCallBack	iCallBack;		   // Where to report the PartitionInfo completion
    70 	TMMCCallBack	iCallBack;		   // Where to report the PartitionInfo completion
    55 	DMMCSession*	iSession;
    71 	DMMCSession*	iSession;
    57 	TUint8* 		iIntBuf;
    73 	TUint8* 		iIntBuf;
    58 	TUint32 		iPartitionAttributes[KMaxLocalDrives];
    74 	TUint32 		iPartitionAttributes[KMaxLocalDrives];
    59 	TBool           iCheckTOC;
    75 	TBool           iCheckTOC;
    60 	Toc*            iTocPtr;
    76 	Toc*            iTocPtr;
    61 	TUint32			iSelectedPartition;	
    77 	TUint32			iSelectedPartition;	
       
    78 	TMediaRequest   iMedReq;
       
    79 	
       
    80 // Version Info Stuff	
       
    81 	TBool            iVersionInfoRead;    
       
    82     TUint32          iVersionInfoItems; /** Amount of version info items */
       
    83     TVersionInfoItem iVersionInfo[KMaxSectionItems]; /** Array for keep whole Version Info structures */
       
    84     TUint32          iTocCount;
    62 	};
    85 	};
       
    86 
       
    87 /*****************************************************************************/
       
    88 /*                                                                           */
       
    89 /* NAME                                                                      */
       
    90 /*      halFunction                                                          */
       
    91 /* DESCRIPTION                                                               */
       
    92 /*      This function gets HAL queries via EHalGroupMedia device 1           */
       
    93 /*      This function is registered in the end of DoCreate                   */
       
    94 /* PARAMETERS                                                                */
       
    95 /*      TAny* aPtr      pointer to DMediaDriverNand object                   */
       
    96 /*      TInt  aFunction requested function:                                  */
       
    97 /*            1 - NAND block size                                            */
       
    98 /*            2 - Is separate erase command supported  ETrue/EFalse          */
       
    99 /*      TAny* a1        address to user side variable, block size is saved   */
       
   100 /*                      to this address                                      */
       
   101 /*      TAny* a2        not used                                             */
       
   102 /* RETURN VALUES                                                             */
       
   103 /*      KErrNone                                                             */
       
   104 /* NOTES                                                                     */
       
   105 /*                                                                           */
       
   106 /*****************************************************************************/
       
   107 LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
       
   108     {
       
   109     DBB5PartitionInfo* pI = (DBB5PartitionInfo*)aPtr;
       
   110     return pI->HalFunction(aFunction,a1,a2);
       
   111     }
    63 
   112 
    64 DBB5PartitionInfo::DBB5PartitionInfo()
   113 DBB5PartitionInfo::DBB5PartitionInfo()
    65   : iSessionEndCallBack(DBB5PartitionInfo::SessionEndCallBack, this),
   114   : iSessionEndCallBack(DBB5PartitionInfo::SessionEndCallBack, this),
    66     iCheckTOC(EFalse)
   115     iCheckTOC(EFalse),iMedReq(EIdle),iVersionInfoItems(0)
    67 	{
   116 	{
    68 	}
   117 	}
    69 
   118 
    70 DBB5PartitionInfo::~DBB5PartitionInfo()
   119 DBB5PartitionInfo::~DBB5PartitionInfo()
    71 	{
   120 	{
    72 	delete iSession;
   121 	delete iSession;
       
   122 	if (iVersionInfoRead)
       
   123 	    {
       
   124 	    TInt r = Kern::RemoveHalEntry(EHalGroupNandMedia,ENandMediaDevice1);
       
   125 	    __KTRACE_OPT(KPBUSDRV, Kern::Printf("~DBB5PartitionInfo: Removed HAL Entry %d",r));
       
   126 	    r = r; //get rid of warning, nothing we can do with the warning
       
   127 	    }
       
   128 	
       
   129 	if (iTocPtr)
       
   130 	    {
       
   131 	    delete iTocPtr;
       
   132 	    }
    73 	}
   133 	}
    74 
   134 
    75 TInt DBB5PartitionInfo::Initialise(DMediaDriver* aDriver)
   135 TInt DBB5PartitionInfo::Initialise(DMediaDriver* aDriver)
    76 	{
   136 	{
    77 	iDriver = aDriver;
   137 	iDriver = aDriver;
    94 	TInt bufLen, minorBufLen;
   154 	TInt bufLen, minorBufLen;
    95 	stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
   155 	stack->BufferInfo(iIntBuf, bufLen, minorBufLen);
    96 
   156 
    97 	iSelectedPartition = TExtendedCSD::ESelectUserArea;
   157 	iSelectedPartition = TExtendedCSD::ESelectUserArea;
    98 	
   158 	
       
   159 	iTocPtr = new Toc();
       
   160 	
    99 	return(KErrNone);
   161 	return(KErrNone);
   100 	}
   162 	}
   101 
   163 
   102 TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack)
   164 TInt DBB5PartitionInfo::PartitionInfo(TPartitionInfo& aInfo, const TMMCCallBack& aCallBack)
   103 	{
   165 	{
       
   166     __KTRACE_OPT(KPBUSDRV,Kern::Printf(">DBB5PartitionInfo:PartitionInfo"));
   104 	iPartitionInfo = &aInfo;
   167 	iPartitionInfo = &aInfo;
   105 	iPartitionInfo->iPartitionCount = 0;
   168 	iPartitionInfo->iPartitionCount = 0;
   106 	iCallBack = aCallBack;
   169 	iCallBack = aCallBack;
       
   170 	iVersionInfoRead = EFalse;
   107 
   171 
   108 	// Always check the user partition first
   172 	// Always check the user partition first
   109 	iSelectedPartition = TExtendedCSD::ESelectUserArea;
   173 	iSelectedPartition = TExtendedCSD::ESelectUserArea;
   110 	iSession->SetPartition(iSelectedPartition);
   174 	iSession->SetPartition(iSelectedPartition);
   111 
   175 
   112 	// Preferred partition scheme is BB5, which is located in the last block of the media.
   176 	// Preferred partition scheme is BB5, which is located in the last block of the media.
   113     TUint32 ptiOffset;
   177     TUint32 ptiOffset = 0;
   114     TInt r;
   178     TInt r = KErrNone;
   115     do
   179     do
   116     	{
   180     	{
   117 	    r = GetPartitionOffset(ptiOffset);
   181 	    r = GetPartitionOffset(ptiOffset);
   118 
   182 
   119 	    if(r == KErrNone)
   183 	    if(r == KErrNone)
   120 	    	{
   184 	    	{
   121 		    r = ReadPartition(ptiOffset);
   185 		    r = ReadPartition(ptiOffset);
   122 		    return r;
   186 		    iMedReq = (KErrNone==r) ? EDecodeBB5PartitionInfo : EIdle;
       
   187 		    break;
   123 	    	}
   188 	    	}
   124 
   189 
   125 	    r = SelectNextPartition();
   190 	    r = SelectNextPartition();
   126     	}
   191     	}
   127     while(r != KErrNotFound);
   192     while(r != KErrNotFound);    
   128 
   193     
       
   194     __KTRACE_OPT(KPBUSDRV,Kern::Printf("<DBB5PartitionInfo::PartitionInfo(%d)",r));
   129 	return r;
   195 	return r;
   130 	}
   196 	}
   131 	
   197 	
   132 // retrieves size in terms of sectors
   198 // retrieves size in terms of sectors
   133 TInt DBB5PartitionInfo::GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize)
   199 TInt DBB5PartitionInfo::GetPartitionSizeInSectors(TUint aPartition, TUint32& aSize)
   134 	{
   200 	{
       
   201     __KTRACE_OPT(KPBUSDRV,Kern::Printf(">DBB5PartitionInfo: GetPartitionSizeInSectors(%d)",aPartition));
       
   202     
   135 	TInt r = KErrNone;
   203 	TInt r = KErrNone;
   136 	
       
   137 	TUint32 size = 0;
   204 	TUint32 size = 0;
   138 	
       
   139 	const TExtendedCSD& extCsd = iCard->ExtendedCSD();
   205 	const TExtendedCSD& extCsd = iCard->ExtendedCSD();
   140 	
   206 	
   141 	switch(aPartition)
   207 	switch(aPartition)
   142 		{
   208 		{
   143 		case TExtendedCSD::ESelectUserArea:
   209 		case TExtendedCSD::ESelectUserArea:
   187 			size = 0;
   253 			size = 0;
   188 			r = KErrNotSupported;
   254 			r = KErrNotSupported;
   189 			break;
   255 			break;
   190 		}
   256 		}
   191 
   257 
       
   258 	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<DBB5PartitionInfo: GetPartitionSizeInSectors(size %d, r %d)",size,r));
   192 	aSize = size;	
   259 	aSize = size;	
   193 	return r;
   260 	return r;
   194 	}
   261 	}
   195 	
   262 	
   196 TInt DBB5PartitionInfo::GetPartitionOffset(TUint32& aPtiOffset)
   263 TInt DBB5PartitionInfo::GetPartitionOffset(TUint32& aPtiOffset)
   211 	return r;
   278 	return r;
   212 	}
   279 	}
   213 	
   280 	
   214 TInt DBB5PartitionInfo::SelectNextPartition()
   281 TInt DBB5PartitionInfo::SelectNextPartition()
   215 	{
   282 	{
       
   283     __KTRACE_OPT(KPBUSDRV,Kern::Printf(">DBB5PartitionInfo: SelectNextPartition (%d)",iSelectedPartition));
   216 	TExtendedCSD extCsd = iCard->ExtendedCSD();
   284 	TExtendedCSD extCsd = iCard->ExtendedCSD();
   217 	TUint maxPartition = TExtendedCSD::ESelectUserArea;
   285 	TUint maxPartition = TExtendedCSD::ESelectUserArea;
   218 	
   286 	
   219 	if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
   287 	if(extCsd.ExtendedCSDRev() >= TExtendedCSD::EExtendedCSDRev1_5)
   220 		{
   288 		{
   226 		{
   294 		{
   227 		// v4.3 supports up to two BOOT partitions
   295 		// v4.3 supports up to two BOOT partitions
   228 		maxPartition = TExtendedCSD::ESelectBootPartition2;
   296 		maxPartition = TExtendedCSD::ESelectBootPartition2;
   229 		}
   297 		}
   230 #endif // EMMC_BOOT_PARTITION_ACCESS_ENABLED
   298 #endif // EMMC_BOOT_PARTITION_ACCESS_ENABLED
   231 
   299 	
   232 	++iSelectedPartition;
   300 	++iSelectedPartition;
   233 	
   301 	
   234 	// skip through to GPAP1 if either the currently selected partition is RPMB or
   302 	// skip through to GPAP1 if either the currently selected partition is RPMB or
   235 	// if it is one of the BOOT partitions and boot partition access is not enabled
   303 	// if it is one of the BOOT partitions and boot partition access is not enabled
   236 	if((iSelectedPartition == TExtendedCSD::ESelectRPMB)
   304 	if((iSelectedPartition == TExtendedCSD::ESelectRPMB)
   250 		}
   318 		}
   251 	else
   319 	else
   252 		{
   320 		{
   253 		iSession->SetPartition(iSelectedPartition);
   321 		iSession->SetPartition(iSelectedPartition);
   254 		}
   322 		}
   255 		
   323 
       
   324 	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<DBB5PartitionInfo: SelectNextPartition (%d) err (%d)",iSelectedPartition, r));
       
   325 	        
   256 	return r;	
   326 	return r;	
   257 	}	
   327 	}	
   258 	
   328 
   259 // returns KErrCompletion on success after having checked all partitions
       
   260 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset)
   329 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset)
   261     {
   330     {
       
   331     return ReadPartition(aPtOffset,1);
       
   332     }
       
   333 
       
   334 // returns KErrCompletion on success after having checked all partitions
       
   335 TInt DBB5PartitionInfo::ReadPartition(TUint32 aPtOffset, TUint aNumBlocks)
       
   336     {
       
   337     __ASSERT_ALWAYS(aNumBlocks > 0,Kern::Fault("DBB5PartitionInfo:RP aNumBlocks = 0", __LINE__));
   262 	// If media driver is persistent (see EMediaDriverPersistent)
   338 	// If media driver is persistent (see EMediaDriverPersistent)
   263 	// the card may have changed since last power down, so reset CID
   339 	// the card may have changed since last power down, so reset CID
   264 	iSession->SetCard(iCard);
   340 	iSession->SetCard(iCard);
   265 
   341 
   266 	iSession->SetupCIMReadBlock(aPtOffset, iIntBuf);
   342 	if (aNumBlocks == 1)
       
   343 	    {
       
   344 	    iSession->SetupCIMReadBlock(aPtOffset, iIntBuf);
       
   345 	    }
       
   346 	else
       
   347 	    {
       
   348 	    iSession->SetupCIMReadBlock(aPtOffset, iIntBuf,aNumBlocks);	    
       
   349 	    }
   267 	
   350 	
   268 	TInt r = iDriver->InCritical();
   351 	TInt r = iDriver->InCritical();
   269 	if (r == KErrNone)
   352 	if (r == KErrNone)
   270 		r = iSession->Engage();
   353 		r = iSession->Engage();
   271 
   354 
   319 
   402 
   320 void DBB5PartitionInfo::DoSessionEndCallBack()
   403 void DBB5PartitionInfo::DoSessionEndCallBack()
   321 	{
   404 	{
   322 	iDriver->EndInCritical();
   405 	iDriver->EndInCritical();
   323 
   406 
       
   407 	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">DBB5PartitionInfo:DoSessionEndCallBack (%d)",iMedReq));
       
   408 	
   324 	TInt r = iSession->EpocErrorCode();
   409 	TInt r = iSession->EpocErrorCode();
   325 
   410 	
   326 	
   411 	if (KErrNone == r)
   327 	TInt& partitionCount = iPartitionInfo->iPartitionCount;
   412 	    {
   328 
   413 	    switch (iMedReq)
   329 	if (r == KErrNone)
   414 	        {
   330 		r = DecodePartitionInfo();
   415 	        case EDecodeBB5PartitionInfo   : 
   331 
   416 	            {
   332 	if (iCheckTOC)
   417                 r = DecodeBB5PartitionInfo();
   333 		{
   418                 if (r == KErrNotFound)
   334 		//BB5 table not found need to check for TOC in this partition before continuing
   419                     {
   335 		if (r!=KErrNone)
   420                     // Check for TOC in this partition instead
   336 			{
   421                     TUint32 size = 0;
   337 			iDriver->PartitionInfoComplete(KErrNotReady);
   422                     r = GetPartitionSizeInSectors(iSelectedPartition,size);
   338 			}
   423                     if ((KErrNone == r) && (size >= KTocStartSector+1))
   339 		return;
   424                         {
   340 		}
   425                         //Check partition size to see if TOC could be read (i.e. might be too small)
   341 
   426                         r = ReadPartition(KTocStartSector);
   342 
   427                         iMedReq = (KErrNone==r) ? EDecodeTOCPartitionInfo : EIdle;
       
   428                         return;
       
   429                         }                    
       
   430                     }
       
   431                 // else - found BB5 check if next phys partition has anything to read...
       
   432                 break;
       
   433 	            }
       
   434 	        case EDecodeTOCPartitionInfo   :
       
   435 	            {
       
   436 	            r = DecodeTOCPartitionInfo();
       
   437 	            if (r == KErrNone)
       
   438 	                {
       
   439 	                //Found a TOC, read version info if available
       
   440 	                TUint32 versOffset = 0;
       
   441 	                iTocCount = 0; //Reset Toc entry counter
       
   442 	                r = ReadTOCVersionInfo(versOffset);	                
       
   443 	                if (r == KErrNotFound)
       
   444 	                    {
       
   445 	                    // No valid partitions present
       
   446 	                    iMedReq = EIdle;
       
   447                         r = KErrNone;
       
   448 	                    }
       
   449 	                else
       
   450 	                    {
       
   451 	                    // Found something to read...
       
   452 	                    r = ReadPartition(versOffset, 2);
       
   453 	                    iMedReq = (KErrNone==r) ? EReadImageVersionInfo : EIdle;
       
   454 	                    return;
       
   455 	                    }
       
   456 	                }
       
   457 	            else
       
   458 	                {
       
   459 	                // TOC not found move on to next phys partition
       
   460 	                iMedReq = EIdle;
       
   461 	                r = KErrNone;
       
   462 	                }
       
   463 	            break;
       
   464 	            }
       
   465 	        case EReadImageVersionInfo     :
       
   466 	            {	            
       
   467                 DecodeVersionInfo();
       
   468                 TUint32 versOffset = 0;
       
   469                 iTocCount++;
       
   470                 r = ReadTOCVersionInfo(versOffset);
       
   471                 if (r == KErrNotFound)
       
   472                     {
       
   473                     //Finished parsing the current TOC                                 
       
   474                     //Mark version info as being read in order to report when finished later
       
   475                     iVersionInfoRead = ETrue;
       
   476                     iMedReq = EIdle;
       
   477                     r=KErrNone;
       
   478                     }
       
   479                 else if (r==KErrNone)
       
   480                     {
       
   481                     // more partitions to read
       
   482                     r = ReadPartition(versOffset, 2);
       
   483                     iMedReq = (KErrNone==r) ? EReadImageVersionInfo : EIdle;
       
   484                     return;
       
   485                     }
       
   486                 break;
       
   487 	            }
       
   488 	            
       
   489 	        default : Kern::Fault("DBB5PartitionInfo unknown request type", __LINE__);
       
   490 	        }
       
   491 	    }
       
   492 	
       
   493 	// Next physical partition will be search for if
       
   494 	// BB5 entry was found, no TOC entry was found or no Version Information was found
   343 	if(r == KErrNone)
   495 	if(r == KErrNone)
   344 		{
   496 		{
   345 		// check next partition(s) for BB5
   497 		// check next partition(s) for BB5
   346 		TUint32 ptiOffset = 0;
   498 		TUint32 ptiOffset = 0;
   347 	
   499 	
   352 				r = GetPartitionOffset(ptiOffset);
   504 				r = GetPartitionOffset(ptiOffset);
   353 				
   505 				
   354 			if(r == KErrNone)
   506 			if(r == KErrNone)
   355 				{
   507 				{
   356 				r = ReadPartition(ptiOffset);
   508 				r = ReadPartition(ptiOffset);
       
   509 				iMedReq = (KErrNone==r) ? EDecodeBB5PartitionInfo : EIdle;
   357 				if(r != KErrNone)
   510 				if(r != KErrNone)
   358 					break;
   511 					break;
   359 
       
   360 
   512 
   361 				return;
   513 				return;
   362 				}
   514 				}
   363 
   515 
   364 			r = SelectNextPartition();
   516 			r = SelectNextPartition();
   369 		if(r != KErrNotFound)
   521 		if(r != KErrNotFound)
   370 			{
   522 			{
   371 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: ReadPartition() failed r=%d!", r));
   523 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: ReadPartition() failed r=%d!", r));
   372 			r = KErrCorrupt;
   524 			r = KErrCorrupt;
   373 			}
   525 			}
   374 		else if(partitionCount == 0)
   526 		else if(iPartitionInfo->iPartitionCount == 0)
   375 			{
   527 			{
   376 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: No supported partitions found!"));
   528 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc:dsc: No supported partitions found!"));
   377 			r = KErrCorrupt;
   529 			r = KErrCorrupt;
   378 			}
   530 			}
   379 		else
   531 		else
   380 			r = KErrCompletion;
   532 			r = KErrCompletion;
   381 		}
   533 		}
       
   534 	
       
   535 	
       
   536 	if (iVersionInfoRead)
       
   537 	    {
       
   538 	    __KTRACE_OPT(KPBUSDRV, Kern::Printf("%d Version Headers - Register HAL entry", iVersionInfoItems ));
       
   539 	    //finished parsing the TOC register HAL function            
       
   540 	    r = Kern::AddHalEntry(EHalGroupNandMedia, halFunction, this, ENandMediaDevice1);
       
   541 	    if (r==KErrNone)
       
   542 	        {	        
       
   543 	        __KTRACE_OPT(KPBUSDRV,Kern::Printf("DBB5PartitionInfo:Added HAL Entry %d",r));
       
   544 	        r = KErrCompletion; //re-mark as completed
       
   545 	        }
       
   546 	    }
   382 
   547 
   383 	// Notify medmmc that partitioninfo is complete
   548 	// Notify medmmc that partitioninfo is complete
   384 	iCallBack.CallBack();
   549 	iCallBack.CallBack();
   385 
   550 
   386 	// All potential partitions checked - KErrCompletion
   551 	// All potential partitions checked - KErrCompletion
   387 	// indicates that there are no more partitions to check
   552 	// indicates that there are no more partitions to check
   388 	r = (r == KErrCompletion) ? KErrNone : KErrNotReady;
   553 	r = (r == KErrCompletion) ? KErrNone : KErrNotReady;
       
   554 	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<DBB5PartitionInfo:PartitionInfo Complete %d",r));
   389 	iDriver->PartitionInfoComplete(r);
   555 	iDriver->PartitionInfoComplete(r);
   390 	}
   556 	}
   391 
   557 
   392 
   558 TInt DBB5PartitionInfo::CheckPartitionBoundaries(TInt aStart, TInt aEnd)
   393 TInt DBB5PartitionInfo::DecodePartitionInfo()
   559     {
       
   560     __ASSERT_ALWAYS(aStart >= 0,Kern::Fault("DBB5PartitionInfo:CPB aStart <0", __LINE__));
       
   561     __ASSERT_ALWAYS(aEnd > 0,Kern::Fault("DBB5PartitionInfo:CPB aEnd <=0", __LINE__));
       
   562     
       
   563     // Validate partition address boundaries
       
   564     TUint32 eMmcPartitionSizeInSectors = 0;
       
   565     TInt r = KErrNone;
       
   566     
       
   567     if (aStart != aEnd)
       
   568         {
       
   569         // At least one entry for a supported partition found
       
   570         r = GetPartitionSizeInSectors(iSelectedPartition, eMmcPartitionSizeInSectors);
       
   571         
       
   572         if(r != KErrNone)
       
   573             {
       
   574             __KTRACE_OPT(KPBUSDRV, Kern::Printf("DBB5PartitionInfo:CPB: Could not retrieve size for eMMC partition 0x%02X", iSelectedPartition));
       
   575             r = KErrCorrupt;
       
   576             }
       
   577         
       
   578     
       
   579         // Check that the eMmcPartition address space boundary is not exceeded by the last partition
       
   580         if(r == KErrNone)
       
   581             {
       
   582             TUint64 eMmcPartitionSize = eMmcPartitionSizeInSectors * KSectorSize;
       
   583             
       
   584             TPartitionEntry& part = iPartitionInfo->iEntry[aEnd - 1];
       
   585                 
       
   586             if(((TUint64)(part.iPartitionBaseAddr + part.iPartitionLen)) > eMmcPartitionSize)
       
   587                 {
       
   588                 __KTRACE_OPT(KPBUSDRV, Kern::Printf("DBB5PartitionInfo:CPB: Partition #%d exceeds eMmc address space", aEnd));
       
   589                 r = KErrCorrupt;
       
   590                 }
       
   591             }
       
   592             
       
   593         if(r == KErrNone)
       
   594             {
       
   595             // Go through all BB5 partition entries on this eMMC partition and check boundaries
       
   596             for(TInt i = aEnd - 1; i > aStart; i--)
       
   597                 {
       
   598                 const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
       
   599                 TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
       
   600     
       
   601                 // Check if partitions overlap
       
   602                 if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
       
   603                     {
       
   604                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("DBB5PartitionInfo:CPB: Overlapping partitions - check #%d", i));
       
   605                     r = KErrCorrupt;
       
   606                     }
       
   607                 }
       
   608             }
       
   609         }
       
   610     
       
   611     return r;
       
   612     }
       
   613 
       
   614 TInt DBB5PartitionInfo::DecodeBB5PartitionInfo()
   394 //
   615 //
   395 // Decode partition info that was read into internal buffer
   616 // Decode partition info that was read into internal buffer
   396 //
   617 //
   397 	{
   618     {
   398 	__KTRACE_OPT(KPBUSDRV, Kern::Printf(">Mmc:PartitionInfo()"));
   619     __KTRACE_OPT(KPBUSDRV, Kern::Printf(">DBB5PartitionInfo: DecodeBB5PartitionInfo(%d)",iPartitionInfo->iPartitionCount));
   399 	TInt& partitionCount = iPartitionInfo->iPartitionCount;
   620     TInt partitionCount = iPartitionInfo->iPartitionCount;
       
   621     TInt r = KErrNotFound;
       
   622         
       
   623 #ifdef __PRINT_RAW_ENTRIES
       
   624     Kern::Printf("BB5 Entry");
       
   625     for (TUint i = 0; i < 512; i+=8)
       
   626         {
       
   627         Kern::Printf("%02x %02x %02x %02x   %02x %02x %02x %02x", iIntBuf[i],iIntBuf[i+1],iIntBuf[i+2],iIntBuf[i+3],iIntBuf[i+4],iIntBuf[i+5],iIntBuf[i+6],iIntBuf[i+7]);
       
   628         }
       
   629 #endif    
       
   630     
       
   631     // Try utilising the BB5 partitioning scheme    
       
   632     BGAHSMMCPTN_PI_STR *partitionTable = (BGAHSMMCPTN_PI_STR*)(&iIntBuf[0]);
       
   633 
       
   634     // Verify that this is the BB5 partition table
       
   635     if( memcompare( (TUint8*)&(partitionTable->iId[0]), sizeof(BGAHSMMCPTN_PI_ID), (TUint8*)BGAHSMMCPTN_PI_ID, sizeof(BGAHSMMCPTN_PI_ID)) == 0 )
       
   636         {
       
   637         __KTRACE_OPT(KPBUSDRV, Kern::Printf("Nokia partition structure found"));
       
   638         __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->id..............: %s", partitionTable->iId ));
       
   639         __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->sector_size.....: %d = 0x%x", partitionTable->iSector_size, partitionTable->iSector_size));
       
   640         __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->major_ver.......: %d", partitionTable->iMajor_ver));
       
   641         __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->minor_ver.......: %d", partitionTable->iMinor_ver));
       
   642         __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->partition_amount: %d", partitionTable->iPartition_amount));
       
   643         
       
   644         TUint8 partitionType = 0;       
       
   645         // Check Supported Version is present
       
   646         if (partitionTable->iMajor_ver <= BGAHSMMCPTN_PI_VER_MAJOR)
       
   647             {
       
   648             for( TUint8 index = 0; (index < partitionTable->iPartition_amount) && (index < BGAHSMMCPTN_LAST_DRIVE); index++ )
       
   649                 {
       
   650                 if (partitionTable->iMinor_ver >= BGAHSMMCPTN_PART_TYPE_SUPP_VER_MINOR)
       
   651                     partitionType = partitionTable->iPartitions[index].iPartition_type;
       
   652                 else                    
       
   653                     partitionType = partitionTable->iPartitions[index].iPartition_id;
       
   654             
       
   655                 // FAT/PMM/CPS/SWAP/CORE/ROFS/CRASH
       
   656                 if( (partitionTable->iPartitions[index].iSize > 0) &&
       
   657                     ( PartitionIsFAT(partitionType) ||
       
   658                       PartitionIsFAT32(partitionType) ||
       
   659                      (KPartitionTypeSymbianCrashLog == partitionType) ||
       
   660                      (KPartitionTypePartitionMagic == partitionType) || //CPS/PMM
       
   661                      (KPartitionTypeRofs == partitionType) || 
       
   662                      (KPartitionTypeEmpty == partitionType) ||
       
   663                      (KPartitionTypeROM == partitionType) ||
       
   664                      (KPartitionTypePagedData == partitionType) ) )
       
   665                     {                   
       
   666                     iPartitionInfo->iEntry[partitionCount].iPartitionType     = partitionType;
       
   667                     iPartitionAttributes[partitionCount]                      = partitionTable->iPartitions[index].iPartition_attributes;
       
   668                     static_cast<DMmcMediaDriverFlash *>(iDriver)->SetEMmcPartitionMapping(partitionCount, iSelectedPartition);
       
   669                     // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS.
       
   670                     const TUint32 KStartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0;
       
   671                     
       
   672                     iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KStartOffset) << KDiskSectorShift;
       
   673                     iPartitionInfo->iEntry[partitionCount].iPartitionLen      = ((Int64) partitionTable->iPartitions[index].iSize - KStartOffset) << KDiskSectorShift;
       
   674     
       
   675                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount));
       
   676                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount));
       
   677                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector ));
       
   678                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift)));
       
   679                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize ));
       
   680                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift));
       
   681                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType));
       
   682                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount]));
       
   683                     __KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionMapping.: 0x%x", static_cast<DMmcMediaDriverFlash *>(iDriver)->GetEMmcPartitionMapping(partitionCount)));
       
   684                     __KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
       
   685     
       
   686                     partitionCount++;
       
   687                     r = KErrNone;
       
   688                     }
       
   689                 }
       
   690             }
       
   691         
       
   692         if(partitionCount > iPartitionInfo->iPartitionCount)
       
   693             {
       
   694             __KTRACE_OPT(KPBUSDRV, Kern::Printf("DBB5PartitionInfo: New BB5 partitions found"));
       
   695 #ifdef __DEBUG_CHECK_PARTITION_         
       
   696             r = CheckPartitionBoundaries(iPartitionInfo->iPartitionCount,partitionCount);        
       
   697             if (r == KErrNone)
       
   698 #endif // __DEBUG_CHECK_PARTITION_             
       
   699                 {
       
   700                 //Update master partition count
       
   701                 iPartitionInfo->iPartitionCount = partitionCount;
       
   702                 iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
       
   703                 }                
       
   704             }
       
   705         }
       
   706     
       
   707     __KTRACE_OPT(KPBUSDRV, Kern::Printf("< DBB5PartitionInfo: DecodeBB5PartitionInfo(%d)",r));
       
   708     return r;
       
   709     }
       
   710 
       
   711 
       
   712 TInt DBB5PartitionInfo::DecodeTOCPartitionInfo()
       
   713 //
       
   714 // Decode partition info that was read into internal buffer
       
   715 //
       
   716     {
       
   717     __KTRACE_OPT(KPBUSDRV, Kern::Printf(">DBB5PartitionInfo: DecodeTOCPartitionInfo(%d)",iPartitionInfo->iPartitionCount));
       
   718     TInt partitionCount = iPartitionInfo->iPartitionCount;
   400     TInt r = KErrNone;
   719     TInt r = KErrNone;
   401 
   720 
   402 	if (iCheckTOC)
   721     // Try utilising the TOC (Table Of Contents) partitioning scheme 
   403 	    {
   722     const TText8* KRofsNames[KNoOfROFSPartitions] = { KTocRofs1Generic,
   404         // Try utilising the TOC (Table Of Contents) partitioning scheme 
   723                                                       KTocRofs2Generic,
   405         const TText8* KRofsNames[KNoOfROFSPartitions] = { KTocRofs1Generic,
   724                                                       KTocRofs3Generic,
   406                                                           KTocRofs2Generic,
   725                                                       KTocRofs4Generic,
   407                                                           KTocRofs3Generic,
   726                                                       KTocRofs5Generic,                                                            
   408                                                           KTocRofs4Generic,
   727                                                       KTocRofs6Generic,                                                            
   409                                                           KTocRofs5Generic,                                                            
   728                                                       };
   410                                                           KTocRofs6Generic,                                                            
   729                                     
   411                                                           };
   730     STocItem item;    
   412                                         
   731     memcpy( iTocPtr, &iIntBuf[0], sizeof(Toc));
   413         STocItem item;
   732 
   414         iTocPtr = reinterpret_cast<Toc*>(&iIntBuf[0]);
   733 #ifdef __PRINT_RAW_ENTRIES
   415         iTocPtr->iTocStartSector = KTocStartSector;
   734     Kern::Printf("TOC Entry");
       
   735     for (TUint i = 0; i < 512; i+=8)
       
   736         {
       
   737         Kern::Printf("%02x %02x %02x %02x   %02x %02x %02x %02x", iIntBuf[i],iIntBuf[i+1],iIntBuf[i+2],iIntBuf[i+3],iIntBuf[i+4],iIntBuf[i+5],iIntBuf[i+6],iIntBuf[i+7]);
       
   738         }
       
   739 #endif   
       
   740         
       
   741     iTocPtr->iTocStartSector = KTocStartSector;
   416 
   742 
   417 // USER Drive - Only 1        
   743 // USER Drive - Only 1        
   418         r = iTocPtr->GetItemByName(KTocUserName, item); 
   744     r = iTocPtr->GetItemByName(KTocUserName, item); 
   419         if (KErrNone == r)
   745     if (KErrNone == r)
       
   746         {
       
   747         __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
       
   748         iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeFAT16;           
       
   749         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64)item.iStart;                         
       
   750         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64)item.iSize;
       
   751         iPartitionAttributes[partitionCount] = 0; // No Additional Attributes required.           
       
   752         partitionCount++;
       
   753         }   
       
   754     
       
   755 // ROM Drive        
       
   756     r = iTocPtr->GetItemByName(KTocRomGeneric, item); 
       
   757     if (KErrNone == r)
       
   758         {
       
   759         __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%x  Size = 0x%x", item.iFileName, item.iStart, item.iSize));
       
   760         iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeROM;           
       
   761         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);                         
       
   762         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);          
       
   763         partitionCount++;
       
   764         }
       
   765     
       
   766 // ROFS            
       
   767     for (TUint i = 0; i < KNoOfROFSPartitions; i++)
       
   768         {
       
   769         /* Search ROFSn item */            
       
   770         r = iTocPtr->GetItemByName(KRofsNames[i], item);
       
   771         if (r == KErrNone)
   420             {
   772             {
   421             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   773             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   422             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeFAT16;           
   774             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeRofs;           
   423             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64)item.iStart;                         
       
   424             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64)item.iSize;
       
   425             iPartitionAttributes[partitionCount] = 0; // No Additional Attributes required.           
       
   426             partitionCount++;
       
   427             }   
       
   428         
       
   429 // ROM Drive        
       
   430         r = iTocPtr->GetItemByName(KTocRomGeneric, item); 
       
   431         if (KErrNone == r)
       
   432             {
       
   433             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%x  Size = 0x%x", item.iFileName, item.iStart, item.iSize));
       
   434             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeROM;           
       
   435             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);                         
   775             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);                         
   436             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);          
   776             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);
   437             partitionCount++;
   777             partitionCount++;
   438             }
   778             }
   439         
   779         }         
   440 // ROFS            
   780 
   441         for (TUint i = 0; i < KNoOfROFSPartitions; i++)
   781 // CPS Drive - Only 1        
       
   782     r = iTocPtr->GetItemByName(KTocCps, item); 
       
   783     if (KErrNone == r)
       
   784         {
       
   785         __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
       
   786         iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypePartitionMagic;           
       
   787         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
       
   788         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
       
   789         partitionCount++;
       
   790         }
       
   791     
       
   792 // CRASH Drive - Only 1        
       
   793     r = iTocPtr->GetItemByName(KTocCrashLog, item); 
       
   794     if (KErrNone == r)
       
   795         {
       
   796         __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
       
   797         iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeSymbianCrashLog;           
       
   798         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
       
   799         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
       
   800         partitionCount++;
       
   801         }
       
   802     
       
   803 // SWAP Partition - Only 1        
       
   804     r = iTocPtr->GetItemByName(KTocSwap, item);
       
   805     if (KErrNone == r)
       
   806         {
       
   807         __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
       
   808         iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypePagedData;           
       
   809         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
       
   810         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
       
   811         partitionCount++;
       
   812         }                
       
   813 
       
   814 #ifdef __DEBUG_PARTITIONS_
       
   815     for (TInt i = 0; i<partitionCount; i++)
       
   816         {
       
   817         Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[i].iPartitionType);                
       
   818         Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[i].iPartitionBaseAddr >> KDiskSectorShift));                
       
   819         Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionLen, iPartitionInfo->iEntry[i].iPartitionLen >> KDiskSectorShift);
       
   820         Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[i]);
       
   821         Kern::Printf(" ");
       
   822         }
       
   823 #endif //__DEBUG_PARTITIONS_
       
   824     
       
   825     if(partitionCount > iPartitionInfo->iPartitionCount)
       
   826         {
       
   827         __KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: New supported partitions found!"));
       
   828 #ifdef __DEBUG_CHECK_PARTITION_         
       
   829         r = CheckPartitionBoundaries(iPartitionInfo->iPartitionCount,partitionCount);        
       
   830         if (r == KErrNone)
       
   831 #endif // __DEBUG_CHECK_PARTITION_             
   442             {
   832             {
   443             /* Search ROFSn item */            
   833             //Update master partition count
   444             r = iTocPtr->GetItemByName(KRofsNames[i], item);
   834             iPartitionInfo->iPartitionCount = partitionCount;
   445             if (r == KErrNone)
   835             iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
   446                 {
   836             r = KErrNone;
   447                 __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   837             }                
   448                 iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeRofs;           
   838         }
   449                 iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart + (KBB5HeaderSizeInSectors << KDiskSectorShift);                         
   839     else
   450                 iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize - (KBB5HeaderSizeInSectors << KDiskSectorShift);
   840         {
   451                 partitionCount++;
   841         __KTRACE_OPT(KPBUSDRV, Kern::Printf("<DBB5PartitionInfo: No New Partitions found - TOC"));
   452                 }
   842         r = KErrNotFound;
   453             }         
   843         }
   454 
   844     
   455 // CPS Drive - Only 1        
   845     __KTRACE_OPT(KPBUSDRV, Kern::Printf("<DBB5PartitionInfo: DecodeTOCPartitionInfo(%d)",r));
   456         r = iTocPtr->GetItemByName(KTocCps, item); 
   846     return r;
   457         if (KErrNone == r)
   847     }
       
   848 
       
   849 
       
   850 // Version Info Support
       
   851 TInt DBB5PartitionInfo::HalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/)
       
   852     {
       
   853     TInt ret = KErrGeneral;  
       
   854 
       
   855     __KTRACE_OPT(KPBUSDRV, Kern::Printf(">DBB5PartitionInfo::HalFunction"));
       
   856     
       
   857     if (aFunction == EGetVersionInfoItems)
       
   858         {
       
   859         __KTRACE_OPT(KPBUSDRV, Kern::Printf(">DBB5PartitionInfo::EGetVersionInfoItems %d Version Headers",iVersionInfoItems ));
       
   860         kumemput32(a1, &iVersionInfoItems, sizeof(TUint32));
       
   861         ret = KErrNone;
       
   862         }
       
   863     else if (aFunction == EGetVersionInfo)
       
   864         {
       
   865         __KTRACE_OPT(KPBUSDRV, Kern::Printf(">DBB5PartitionInfo::EGetVersionInfo"));
       
   866         kumemput32(a1, &iVersionInfo[0], sizeof(TVersionInfoItem)*iVersionInfoItems);
       
   867         ret = KErrNone;
       
   868         }
       
   869 
       
   870     __KTRACE_OPT(KPBUSDRV, Kern::Printf("<DBB5PartitionInfo::HalFunction"));
       
   871     
       
   872     return ret;
       
   873     }
       
   874 
       
   875 // returns KErrNotfound if reached the end of the toc
       
   876 TInt DBB5PartitionInfo::ReadTOCVersionInfo(TUint32& aOffset)
       
   877     {
       
   878     TInt r = KErrNotFound;
       
   879     for (; iTocCount < KMaxNbrOfTocItems; iTocCount++ )
       
   880         {
       
   881         __KTRACE_OPT(KPBUSDRV, Kern::Printf("ReadTOCVersionInfo: Find next usable TOC entry (%d)",iTocCount));
       
   882         // Iterate through the partition info table looking for valid partition headers
       
   883         if ( iTocPtr->iTOC[iTocCount].iStart == KEndOfToc ) 
   458             {
   884             {
   459             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   885             __KTRACE_OPT(KPBUSDRV, Kern::Printf("ReadTOCVersionInfo: End of the TOC"));
   460             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypePartitionMagic;           
   886             break;
   461             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
   887             }    
   462             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
   888         else if ( iTocPtr->iTOC[iTocCount].iStart & 0x80000000 )             
   463             partitionCount++;
   889             {
       
   890             __KTRACE_OPT(KPBUSDRV, Kern::Printf("ReadTOCVersionInfo: Image has negative offset"));
       
   891             continue;
       
   892             }    
       
   893         else if ( iTocPtr->iTOC[iTocCount].iSize <= 1024 ) 
       
   894             {
       
   895             __KTRACE_OPT(KPBUSDRV, Kern::Printf("ReadTOCVersionInfo: entry is less than 2 sectors in size"));
       
   896             continue;
   464             }
   897             }
   465         
   898         
   466 // CRASH Drive - Only 1        
   899         r = KErrNone;
   467         r = iTocPtr->GetItemByName(KTocCrashLog, item); 
   900         break;
   468         if (KErrNone == r)
   901         } 
   469             {
   902     
   470             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   903     if (r == KErrNone)
   471             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypeSymbianCrashLog;           
   904         {
   472             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
   905         aOffset = ((iTocPtr->iTOC[iTocCount].iStart) >> KSectorShift) + (iTocPtr->iTocStartSector);
   473             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
   906         }
   474             partitionCount++;
   907     
   475             }
   908     return r;
   476         
   909     }
   477 // SWAP Partition - Only 1        
   910 
   478         r = iTocPtr->GetItemByName(KTocSwap, item);
   911 void DBB5PartitionInfo::DecodeVersionInfo()
   479         if (KErrNone == r)
   912     {    
   480             {
   913     __KTRACE_OPT(KPBUSDRV,Kern::Printf(">Decode Version Info (%d)",iVersionInfoItems));
   481             __KTRACE_OPT(KPBUSDRV, Kern::Printf("[MD  :   ] (%11s) in TOC found : Start addr = 0x%X  Size = 0x%X", item.iFileName, item.iStart, item.iSize));
   914     
   482             iPartitionInfo->iEntry[partitionCount].iPartitionType     = KPartitionTypePagedData;           
   915 #ifdef __PRINT_RAW_ENTRIES
   483             iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = (Int64) item.iStart;                         
   916     Kern::Printf("Version Info:");
   484             iPartitionInfo->iEntry[partitionCount].iPartitionLen      = (Int64) item.iSize;
   917     for (TUint i = 0; i < 1024; i+=8)
   485             partitionCount++;
   918         {
   486             }                
   919         Kern::Printf("%02x %02x %02x %02x   %02x %02x %02x %02x", iIntBuf[i],iIntBuf[i+1],iIntBuf[i+2],iIntBuf[i+3],iIntBuf[i+4],iIntBuf[i+5],iIntBuf[i+6],iIntBuf[i+7]);
   487 
   920         }
   488 #ifdef __DEBUG_PARTITIONS_
   921 #endif
   489         for (TInt i = 0; i<partitionCount; i++)
   922     
   490             {
   923     // check BB5 common header and image header
   491             Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[i].iPartitionType);                
   924     if ( *(TUint32*)&iIntBuf[0]                  == KBB5_CommonHeaderMagic || 
   492             Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[i].iPartitionBaseAddr >> KDiskSectorShift));                
   925          *(TUint32*)&iIntBuf[KImageHeaderOffset] == KImageHeaderMagic )       
   493             Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[i].iPartitionLen, iPartitionInfo->iEntry[i].iPartitionLen >> KDiskSectorShift);
   926         {
   494             Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[i]);
   927         // pick up required info from TOC
   495             Kern::Printf(" ");
   928         TVersionInfoItem *vinfo = (TVersionInfoItem *)&iVersionInfo[iVersionInfoItems];
   496             }
   929         vinfo->iSectionMaxSize = iTocPtr->iTOC[iTocCount].iSize;
   497 #endif //__DEBUG_PARTITIONS_
   930         memcpy( &vinfo->iSectionName[0], &iTocPtr->iTOC[iTocCount].iFileName[0], KMaxSectionNameLen);
   498         
   931         
   499 		r = KErrNone;
   932         // pick up required info from image header
   500         iCheckTOC = EFalse;
   933         TImageHeader *himage = (TImageHeader *)&iIntBuf[KImageHeaderOffset];
   501 	    }
   934         vinfo->iImageCompressedSize = himage->iImageCompressedSize;
   502 	else
   935         vinfo->iImageSize = himage->iImageSize;
   503 	    {
   936         memcpy( &vinfo->iVersion[0], &himage->iVersion[0], KMaxVersionInfoLen);
   504         // Try utilising the BB5 partitioning scheme	
   937         
   505         BGAHSMMCPTN_PI_STR *partitionTable = (BGAHSMMCPTN_PI_STR*)(&iIntBuf[0]);
   938         
   506     
   939         __KTRACE_OPT(KPBUSDRV,Kern::Printf("Section Name (%11s)",vinfo->iSectionName));
   507         // Verify that this is the Nokia partition table
   940         __KTRACE_OPT(KPBUSDRV,Kern::Printf("Section size (%d)",vinfo->iSectionMaxSize));
   508         if( memcompare( (TUint8*)&(partitionTable->iId[0]), sizeof(BGAHSMMCPTN_PI_ID), (TUint8*)BGAHSMMCPTN_PI_ID, sizeof(BGAHSMMCPTN_PI_ID)) == 0 )
   941         __KTRACE_OPT(KPBUSDRV,Kern::Printf("Compressed Size %d", vinfo->iImageCompressedSize));
   509             {
   942         __KTRACE_OPT(KPBUSDRV,Kern::Printf("Image Size %d", vinfo->iImageSize));
   510 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Nokia partition structure found"));
   943         __KTRACE_OPT(KPBUSDRV,Kern::Printf("VersionInfo (%11s)",vinfo->iVersion));
   511 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->id..............: %s", partitionTable->iId ));
   944         
   512 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->sector_size.....: %d = 0x%x", partitionTable->iSector_size, partitionTable->iSector_size));
   945         iVersionInfoItems++;
   513 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->major_ver.......: %d", partitionTable->iMajor_ver));
   946         }
   514 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->minor_ver.......: %d", partitionTable->iMinor_ver));
   947     
   515 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionTable->partition_amount: %d", partitionTable->iPartition_amount));
   948     __KTRACE_OPT(KPBUSDRV,Kern::Printf("<Decode Version Info (%d)",iVersionInfoItems));
   516             
   949     return;
   517             TUint8 partitionType = 0;		
   950     }
   518             // Check Supported Version is present
       
   519             if (partitionTable->iMajor_ver <= BGAHSMMCPTN_PI_VER_MAJOR)
       
   520                 {
       
   521                 for( TUint8 index = 0; (index < partitionTable->iPartition_amount) && (index < BGAHSMMCPTN_LAST_DRIVE); index++ )
       
   522                     {
       
   523                     if (partitionTable->iMinor_ver >= BGAHSMMCPTN_PART_TYPE_SUPP_VER_MINOR)
       
   524                         partitionType = partitionTable->iPartitions[index].iPartition_type;
       
   525                     else                    
       
   526                         partitionType = partitionTable->iPartitions[index].iPartition_id;
       
   527                 
       
   528                     // FAT/PMM/CPS/SWAP/CORE/ROFS/CRASH
       
   529                     if( (partitionTable->iPartitions[index].iSize > 0) &&
       
   530                         ( PartitionIsFAT(partitionType) ||
       
   531                           PartitionIsFAT32(partitionType) ||
       
   532                          (KPartitionTypeSymbianCrashLog == partitionType) ||
       
   533                          (KPartitionTypePartitionMagic == partitionType) || //CPS/PMM
       
   534                          (KPartitionTypeRofs == partitionType) || 
       
   535                          (KPartitionTypeEmpty == partitionType) ||
       
   536                          (KPartitionTypeROM == partitionType) ||
       
   537                          (KPartitionTypePagedData == partitionType) ) )
       
   538                         {                   
       
   539                         iPartitionInfo->iEntry[partitionCount].iPartitionType	  = partitionType;
       
   540                         iPartitionAttributes[partitionCount]                      = partitionTable->iPartitions[index].iPartition_attributes;
       
   541 	                    static_cast<DMmcMediaDriverFlash *>(iDriver)->SetEMmcPartitionMapping(partitionCount, iSelectedPartition);
       
   542                         // ROM/ROFS partitions have a BB5 checksum header that must be offset for the Symbian OS.
       
   543 						const TUint32 KStartOffset = ((KPartitionTypeROM == partitionType) || (KPartitionTypeRofs == partitionType) || (KPartitionTypeEmpty == partitionType)) ? KBB5HeaderSizeInSectors : 0;
       
   544                         
       
   545                         iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr = ((Int64) partitionTable->iPartitions[index].iStart_sector + KStartOffset) << KDiskSectorShift;
       
   546                         iPartitionInfo->iEntry[partitionCount].iPartitionLen      = ((Int64) partitionTable->iPartitions[index].iSize - KStartOffset) << KDiskSectorShift;
       
   547         
       
   548                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("Registering partition #%d:", partitionCount));
       
   549                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("partitionCount....: %d", partitionCount));
       
   550                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("startSector.......: 0x%x", partitionTable->iPartitions[index].iStart_sector ));
       
   551                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionBaseAddr: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr, (TUint32)(iPartitionInfo->iEntry[partitionCount].iPartitionBaseAddr >> KDiskSectorShift)));
       
   552                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("size..............: 0x%lx", partitionTable->iPartitions[index].iSize ));
       
   553                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionLen.....: 0x%lx (sectors: %d)", iPartitionInfo->iEntry[partitionCount].iPartitionLen, iPartitionInfo->iEntry[partitionCount].iPartitionLen >> KDiskSectorShift));
       
   554                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionType....: %d", iPartitionInfo->iEntry[partitionCount].iPartitionType));
       
   555                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionAttribs.: 0x%x", iPartitionAttributes[partitionCount]));
       
   556 						__KTRACE_OPT(KPBUSDRV, Kern::Printf("iPartitionMapping.: 0x%x", static_cast<DMmcMediaDriverFlash *>(iDriver)->GetEMmcPartitionMapping(partitionCount)));
       
   557                     	__KTRACE_OPT(KPBUSDRV, Kern::Printf(" "));
       
   558         
       
   559                         partitionCount++;
       
   560                         }
       
   561                     }
       
   562                 } 
       
   563             }
       
   564         else
       
   565             {
       
   566             __KTRACE_OPT(KPBUSDRV, Kern::Printf("BGAHSMMC signature not found - try TOC layout"));
       
   567             iCheckTOC = ETrue;
       
   568             
       
   569             TInt r = ReadPartition(KTocStartSector);
       
   570             return r;
       
   571             }
       
   572 	    }
       
   573 	
       
   574 	
       
   575 	// Validate partition address boundaries
       
   576 	if(partitionCount == 0)
       
   577 		{
       
   578 		__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: No supported partitions found!"));
       
   579 		// No Supported partitions found on this physical partition
       
   580 		return KErrNone;
       
   581 		}
       
   582 		
       
   583 #ifdef __DEBUG_CHECK_PARTITION_			
       
   584 	// Validate partition address boundaries
       
   585 	TUint32 eMmcPartitionSizeInSectors = 0;
       
   586 	if(r == KErrNone)
       
   587 		{
       
   588 		// At least one entry for a supported partition found
       
   589 		r = GetPartitionSizeInSectors(iSelectedPartition, eMmcPartitionSizeInSectors);
       
   590 		
       
   591 		if(r != KErrNone)
       
   592 			{
       
   593 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Could not retrieve size for eMMC partition 0x%02X", iSelectedPartition));
       
   594 			r = KErrCorrupt;
       
   595 			}
       
   596 		}
       
   597 		
       
   598 	if(r == KErrNone)
       
   599 		{
       
   600 		TUint64 eMmcPartitionSize = eMmcPartitionSizeInSectors * KSectorSize;
       
   601 		
       
   602 		TPartitionEntry& part = iPartitionInfo->iEntry[partitionCount - 1];
       
   603 	
       
   604 		// Check that the eMmcPartition address space boundary is not exceeded by the last partition
       
   605 		if(part.iPartitionBaseAddr + part.iPartitionLen > eMmcPartitionSize)
       
   606 			{
       
   607 			__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Partition #%d exceeds eMmc address space", partitionCount));
       
   608 			r = KErrCorrupt;
       
   609 			}
       
   610 		}
       
   611 		
       
   612 	if(r == KErrNone)
       
   613 		{
       
   614 		// Go through all BB5 partition entries on this eMMC partition and check boundaries
       
   615 		for(TInt i = partitionCount - 1; i > iPartitionInfo->iPartitionCount; i--)
       
   616 			{
       
   617 			const TPartitionEntry& curr = iPartitionInfo->iEntry[i];
       
   618 			TPartitionEntry& prev = iPartitionInfo->iEntry[i-1];
       
   619 
       
   620 			// Check if partitions overlap
       
   621 			if(curr.iPartitionBaseAddr < (prev.iPartitionBaseAddr + prev.iPartitionLen))
       
   622 				{
       
   623 				__KTRACE_OPT(KPBUSDRV, Kern::Printf("Mmc: Overlapping partitions - check #%d", i));
       
   624 				r = KErrCorrupt;
       
   625 				}
       
   626 			}
       
   627 		}
       
   628 #endif // _DEBUG_CHECK_PARTITION_
       
   629 		
       
   630 	if(r == KErrNone)
       
   631 		{
       
   632 		iPartitionInfo->iPartitionCount = partitionCount;
       
   633 		iPartitionInfo->iMediaSizeInBytes = iCard->DeviceSize64();
       
   634 		}
       
   635 
       
   636 	__KTRACE_OPT(KPBUSDRV, Kern::Printf("<Mmc:PartitionInfo (C:%d)", partitionCount));
       
   637 	return r;
       
   638 	}
       
   639 
   951 
   640 
   952 
   641 // End - DBB5PartitionInfo
   953 // End - DBB5PartitionInfo
   642 
   954 
   643 
   955