brdbootldr/ubootldr/locdrv.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:24:54 +0200
changeset 43 96e5fb8b040d
permissions -rw-r--r--
Revision: 200951 Kit: 200951

// Copyright (c) 2005-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:
// improvised boot loader mechanism
// 
//

/**
 @file
*/

#include <e32const.h>
#include <e32const_private.h>
#include <e32std.h>
#include <e32std_private.h>
#include <e32svr.h>
#include <e32cons.h>
#include <f32file.h>
#include <hal.h>
#include <u32hal.h>
#include "bootloader_variantconfig.h"
#include <nkern/nk_trace.h>
#include <e32twin.h>

#define FILE_ID	0x594D555D
#include "bootldr.h"

void CloseAndDeleteFile();
RFs TheFs;

// Extra stuff to determine inner compression from the ROM header
#include <e32rom.h>
extern TInt memcmp1(const TUint8* aTrg, const TUint8* aSrc, TInt aLength);

// XXX FIXED DRIVE PATH
const TPtrC filePath=_L("d:\\");

#if defined(__SUPPORT_UNZIP__)
const TBool ZipIsSupported = ETrue;
#else
const TBool ZipIsSupported = EFalse;
#endif

#if defined(__SUPPORT_FLASH_REPRO__)
const TBool FlashIsSupported = ETrue;
#else
const TBool FlashIsSupported = EFalse;
#endif

typedef struct 
	{
	TPtrC filename;
	TBool Zip;        // set to ETrue if this file is a ZIP file
	TBool Flash;      // set to ETrue if this file is to be written to flash
	TBool BootLoader; // set to ETrue if this file is to be flashed to the BootLoader address
	TBool Delete;     // set to ETrue if this file is to be deleted after loading into RAM
	}
	TFileTypes;


TFileTypes supportedFileTypes [] =
	{
		// Name              Zip     Flash   BootLoader  Delete
		{_L("FLASHLDR.ZIP"), ETrue,  ETrue,  ETrue,      ETrue   },
		{_L("FLASHLDR.BIN"), EFalse, ETrue,  ETrue,      ETrue   },

		{VARIANT_ZIP,        ETrue,  EFalse, EFalse,     EFalse  },
		{VARIANT_BIN,        EFalse, EFalse, EFalse,     EFalse  },

		{_L("SYS$ROM.ZIP"),  ETrue,  EFalse, EFalse,     EFalse  },
		{_L("SYS$ROM.BIN"),  EFalse, EFalse, EFalse,     EFalse  },

        {_L("FLASHIMG.ZIP"), ETrue,  ETrue,  EFalse,     EFalse  },
		{_L("FLASHIMG.BIN"), EFalse, ETrue,  EFalse,     EFalse  },
        {_L("BOOTLDR.ZIP"),  ETrue,  ETrue,  ETrue,      EFalse  },
		{_L("BOOTLDR.BIN"),  EFalse, ETrue,  ETrue,      EFalse  },

		{_L("COREIMG.BIN"),  EFalse, EFalse, EFalse,     ETrue   },

		{_L(""),0} // Last Entry - this empty row is used in code to detect table end
	};


GLDEF_C TBool SearchDrivesRaw()
	{
	// Scan local drives directly (i.e. via TLocalDrv rather than RFS)
	
	PrintToScreen(_L("Checking local drives directly.\r\n"));
	
	TDriveInfoV1Buf diBuf;
	UserHal::DriveInfo(diBuf);
	TDriveInfoV1 &di=diBuf();
	
	
	LocDrvChg = EFalse;
	LocDrvPos = 0;
	TInt LocalDriveNum = KErrNotFound;
	TInt r = KErrNone;
	TInt n=0;
	for ( ; n<KMaxLocalDrives && LocalDriveNum == KErrNotFound; n++)
		{
		r = LocDrv.Connect(n, LocDrvChg);

		if(r != KErrNone)
			{
			RDebug::Print(_L("\nDrive %d: TBusLocalDrive::Connect() failed %d"), n, r);
			continue;
			}	

	    TLocalDriveCapsV5Buf capsBuf;
	    TLocalDriveCapsV5& caps = capsBuf();
		r = LocDrv.Caps(capsBuf);
		if(r != KErrNone)
			{
			RDebug::Print(_L("\nDrive %d: TBusLocalDrive::Caps() failed %d"), n, r);
			continue;
			}
		else
			{
			PrintToScreen(_L("Found Drive %d OK\r\n"),n);
			RDebug::Print(_L("\nDrive %d: %S"), n, &di.iDriveName[n]);
			RDebug::Print(_L("PartitionType %X"), caps.iPartitionType);
			RDebug::Print(_L("PartitionSize %ld"), caps.iSize);
			
			// Check that drive is labelled as MMC or SDIO, 
			// note that this is a platform specific label...
			if ((di.iDriveName[n].MatchF(_L("MultiMediaCard0")) == KErrNone) ||
			    (di.iDriveName[n].MatchF(_L("SDIOCard0")) == KErrNone))
				{
				if (caps.iPartitionType == KPartitionTypeROM)
					{
					RDebug::Print(_L("- ROM Partition"));
					LocalDriveNum = n;
					FileSize = caps.iSize;
					break;
					}
				}
			
			CloseLocalDrive();
			}
		}
	
	if (LocalDriveNum == KErrNotFound)
		{
		RDebug::Print(_L("No ROM Partitions found"));
		return EFalse;
		}
	else
		{
		RDebug::Print(_L("Query ROM in drive %d"), LocalDriveNum);
		}
	
	InputFunction=ReadFromLocalDrive;
	CloseInputFunction=CloseLocalDrive;
	
	RDebug::Print(_L("Determine the compression"));
	
    r = GetInnerCompression(ImageDeflated, RomLoaderHeaderExists);
    
    if(KErrNone != r)
        {
        PrintToScreen(_L("Unable to determine the compression!\r\n"));
	    BOOT_FAULT();    
        }
    else
    	{
    	// Put position back to start
    	LocDrvPos = 0;
    	}
	
	return ETrue;
	}


TInt ReadFromLocalDrive(TUint8* aDest, TInt& aLength)
	{
	// construct as TPtr8(TUint8 *aBuf, TInt aMaxLength);
	// .. because TBusLocalDrive.Read only understands descriptors
	TPtr8 d(aDest, aLength);
	
	TInt r = LocDrv.Read(LocDrvPos,aLength,d);
	LocDrvPos+=aLength;
	
	if (LocDrvPos >= FileSize)
		{
		// ROM read completely
		r = KErrEof;
		}
	
	return r;
	}


void CloseLocalDrive()
	{
	LocDrv.Disconnect();
	}


GLDEF_C TBool SearchDrives()
	{
	// set up the list of files to look for -- this code will search through
	// all available drives until it finds one of these files in a root
	// directory

	PrintToScreen(_L("Checking local drives.\r\n"));

	// search for files
	TInt r = TheFs.Connect();
	if (r != KErrNone)
		{
		RDebug::Print(_L("FAULT: Connecting RFs returned %d\r\n"),r);
		BOOT_FAULT();
		}

	TFindFile finder(TheFs);

	// for each file in the list
	TInt NrChecked = 0;
	r = KErrNotFound;

	while ( (*(supportedFileTypes[NrChecked].filename.Ptr()) != 0) && (r == KErrNotFound))
		{
		if (  (!ZipIsSupported && (supportedFileTypes[NrChecked].Zip))
		   || (!FlashIsSupported && (supportedFileTypes[NrChecked].Flash))
		   )
			{
			//skip ZIP/FLASH file types if they aren't supported
			}
		else
			{
			TPtrC thisFile = supportedFileTypes[NrChecked].filename;
			r = finder.FindByDir(thisFile, filePath);

			if (r == KErrNone)
				PrintToScreen(_L("Found %s\r\n"), thisFile.Ptr());
			}
		NrChecked++;
		}

	// if found
	if (r == KErrNone)
		{
		// setup some flags 
		LoadFile=--NrChecked; // predecrement since this was incremented at the end of the last loop
		LoadDevice=ELoadDrive;

		const TPtrC bootFileName = finder.File();

		PrintToScreen(_L("Opening: %s\r\n"), supportedFileTypes[NrChecked].filename.Ptr());

		r = bootFile.Open(TheFs, bootFileName, EFileRead);

		if (r != KErrNone)
			{
			PrintToScreen(_L("Bootfile failed to open - err %d.\r\n"),r);

			BOOT_FAULT();
			}

		ImageZip         = supportedFileTypes[NrChecked].Zip;
		LoadToFlash      = supportedFileTypes[NrChecked].Flash;
		FlashBootLoader  = supportedFileTypes[NrChecked].BootLoader;
		
		InputFunction=ReadFromFile;
		CloseInputFunction = supportedFileTypes[NrChecked].Delete ? CloseAndDeleteFile : CloseFile;

        if( !ImageZip)
            {
            r = GetInnerCompression(ImageDeflated, RomLoaderHeaderExists);
            if(KErrNone != r)
                {
                PrintToScreen(_L("Unable to determine the compression!\r\n"));
			    BOOT_FAULT();    
                }
            else
            	{
            	// Move file pos back to the beginning
            	TInt pos = 0;
                r = bootFile.Seek(ESeekStart, pos);
            	}
            }

		r = bootFile.Size(FileSize);

		if (r == KErrNone)
			{
			PrintToScreen(_L("Opened, size: %d bytes.\r\n"), FileSize);
			if(ImageDeflated)
    			{
    			PrintToScreen(_L("ROM Image is deflated.\r\n"));    
    			}
			}
		else
			{
			PrintToScreen(_L("Unable to read file size\r\n"));
			BOOT_FAULT();
			}

		// Found image - return true
		return ETrue;
		}

	// else NOT FOUND
	return EFalse;
	}

TInt ReadFromFile(TUint8* aDest, TInt& aLength)
	{
	// construct as TPtr8(TUint8 *aBuf, TInt aMaxLength);
	// .. because RFile.Read only understands descriptors
	TPtr8 d(aDest, aLength);

	TInt r = bootFile.Read(d);

	if (d.Length() < aLength) // may happen at the end of a file
		{
		aLength = d.Length();
		}

	if (d.Length() == 0)	// indicates end of file
		{
		if (FileSize-aLength == ImageReadProgress)
			return KErrEof;
		else
			// this will drop through to the error code below and will fault
			return KErrGeneral;
		}

	return r;
	}

void CloseFile()
	{
	bootFile.Close();
	}

void CloseAndDeleteFile()
	{
	TFileName fileName;
	TInt r = bootFile.FullName(fileName);
	if (r != KErrNone)
		PrintToScreen(_L("CloseAndDeleteFile() RFile::FullName returned %d"), r);

	bootFile.Close();

	r = TheFs.Delete(fileName);
	PrintToScreen(_L("Deleted file fileName %S"), &fileName);
	}

//#define TROM_LOADER_HEADER_SIZE 0x100
#define BUFFER_SIZE         (TROM_LOADER_HEADER_SIZE + sizeof(TRomHeader))

TInt GetInnerCompression(TBool &aImageDeflated, TBool &aRomLoaderHeaderExists )
    {
    TInt r = KErrNone;
    
    TUint8 buffer[BUFFER_SIZE];
    TInt   bufferSize = BUFFER_SIZE;
    
    const TUint8 * romLoaderSignature1 = (const TUint8*)"EPOC";
    const TUint8 * romLoaderSignature2 = (const TUint8*)"ROM";
    
    r = ReadInputData((TUint8*)&buffer, bufferSize);
	if( KErrNone!=r)
		{
		PrintToScreen(_L("Unable to read loader headers... (size:%d)\r\n"), bufferSize);
		BOOT_FAULT();    
		}
	else
    	{
    	// Check headers
    	TRomHeader* romHeader= (TRomHeader *) &buffer;
    	aRomLoaderHeaderExists = EFalse;
    	
    	if( !memcmp1(buffer, romLoaderSignature1, 4) && !memcmp1(&buffer[8], romLoaderSignature2, 3) )
    	    {
            // We have TRomLoaderHeader skip it
            romHeader = (TRomHeader *) (&buffer[TROM_LOADER_HEADER_SIZE]);
            aRomLoaderHeaderExists = ETrue;
    	    }
    	
        if(romHeader->iCompressionType == 0 )
            {
             RDebug::Print(_L("Image is NOT Compressed"));
             aImageDeflated = EFalse;
             FileSize = romHeader->iUncompressedSize;
             PrintToScreen(_L("ROMSIZE:%d\r\n"), romHeader->iUncompressedSize);
             RDebug::Print(_L("ROMSIZE:%d"), romHeader->iUncompressedSize);
             
         	if (romHeader->iPageableRomStart > 0)
         		{
         		PrintToScreen(_L("Paged ROM FOUND\r\n"));
         		RDebug::Print(_L("Paged ROM FOUND"));
         		FileSize = romHeader->iPageableRomStart;
         		RDebug::Print(_L("Unpaged ROMSIZE:%d"), romHeader->iPageableRomStart);
         		}          
            }
        else if (romHeader->iCompressionType == KUidCompressionDeflate )
            {
            RDebug::Print(_L("Image is Compressed\r\n"));
            aImageDeflated = ETrue;
            FileSize = romHeader->iUnpagedUncompressedSize;
            RDebug::Print(_L("Compressed ROMSIZE:%d\r\n"), romHeader->iUnpagedUncompressedSize);       
            }
        else
            {
            RDebug::Print(_L("Not supported compression method:0x%08x\r\n"), romHeader->iCompressionType);
            PrintToScreen(_L("Not supported compression method:0x%08x\r\n"), romHeader->iCompressionType);
            r = KErrNotSupported;
            }
     	}
	return r;        
    }