brdbootldr/ubootldr/main.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // improvised boot loader mechanism
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20 */
       
    21 
       
    22 #include <e32const.h>
       
    23 #include <e32const_private.h>
       
    24 #include <e32std.h>
       
    25 #include <e32std_private.h>
       
    26 #include <e32svr.h>
       
    27 #include <e32cons.h>
       
    28 #include <f32file.h>
       
    29 #include <hal.h>
       
    30 #include <u32hal.h>
       
    31 #include "bootloader_variantconfig.h"
       
    32 #include <nkern/nk_trace.h>
       
    33 #include <e32twin.h>
       
    34 #include <e32rom.h>
       
    35 
       
    36 #include <hal.h>
       
    37 #include <d32ethernet.h>
       
    38 
       
    39 #define FILE_ID	0x594D555D
       
    40 #include "bootldr.h"
       
    41 #include "ubootldrldd.h"
       
    42 
       
    43 #include <d32comm.h>
       
    44 
       
    45 #ifdef _DEBUG_CORELDR_
       
    46 #define WAIT_TO_REBOOT  10000000
       
    47 #else
       
    48 #define WAIT_TO_REBOOT    100000
       
    49 #endif
       
    50 
       
    51 #define addr_to_page(a) (a&~(0x1000-1))
       
    52 
       
    53 _LIT(KPanicText,"UBOOTLDR");
       
    54 _LIT(LDD_NAME, "Enet");
       
    55 _LIT(PDD_NAME, "Ethernet");
       
    56 
       
    57 // Memory
       
    58 RUBootldrLdd Ldd;
       
    59 RChunk TheRamChunk;		// This is the download area
       
    60 
       
    61 /// Global number of seconds to delay before reboot
       
    62 
       
    63 void GetChunk()
       
    64 	{
       
    65 	TInt PageSize;
       
    66 	UserHal::PageSizeInBytes(PageSize);
       
    67 
       
    68 	TInt r = User::LoadLogicalDevice(KBootldrLddName);
       
    69 
       
    70 	r = Ldd.Open();
       
    71 	if (r!=KErrNone)
       
    72 			{
       
    73 			PrintToScreen(_L("FAULT due to LDD open\r\n"));
       
    74 			BOOT_FAULT();
       
    75 			}
       
    76 
       
    77 	TUint8* kernelAddress;
       
    78 	r=Ldd.CreateChunk(KRamTargetSize,(TAny**)&kernelAddress);
       
    79 	if (r!=KErrNone)
       
    80 			{
       
    81 			PrintToScreen(_L("FAULT due to chunk create\r\n"));
       
    82 			BOOT_FAULT();
       
    83 			}
       
    84 
       
    85 	r = Ldd.CommitMemory(KRamTargetSize,addr_to_page(KRamTargetAddr));
       
    86 	if (r!=KErrNone)
       
    87 			{
       
    88 			PrintToScreen(_L("FAULT due to commit\r\n"));
       
    89 			BOOT_FAULT();
       
    90 			}
       
    91 
       
    92 	r = Ldd.GetChunkHandle(TheRamChunk);
       
    93 	if (r!=KErrNone)
       
    94 			{
       
    95 			PrintToScreen(_L("FAULT due to handle\r\n"));
       
    96 			BOOT_FAULT();
       
    97 			}
       
    98 
       
    99 	TUint8* Base = TheRamChunk.Base();
       
   100 	ActualDestinationAddress = (TUint32*)Base;
       
   101 	}
       
   102 
       
   103 // method of getting the date string at build time
       
   104 // Taken from e32test\device\t_usbco22.cpp
       
   105 #define WIDEN2(x) L ## x
       
   106 #define WIDEN(x) WIDEN2(x)
       
   107 #define __WDATE__ WIDEN(__DATE__)
       
   108 
       
   109 
       
   110 //////////////////////////////////////////////////////////////////////////////
       
   111 //
       
   112 // Application entry point
       
   113 //
       
   114 //////////////////////////////////////////////////////////////////////////////
       
   115 LOCAL_C void RunAppL()
       
   116 	{
       
   117 	TInt r;
       
   118 
       
   119 	// Get the memory download area mapped into a chunk
       
   120 	GetChunk();
       
   121 
       
   122 	// Initialise our graphical screen
       
   123 	InitDisplay();
       
   124 
       
   125 #ifdef __USE_VARIANT_INIT__
       
   126 	// The variant initialisation function is likely to perform bootloader
       
   127 	// configuration or print debug information.
       
   128 	VariantInit();
       
   129 #endif
       
   130 
       
   131 #ifdef __USE_USBMS__
       
   132 	// If the bootloader is in the USB Mass Storage mode (indicated by the Variant
       
   133 	// initialisation routine) then call that method first; it will either read/boot
       
   134 	// an image, start the USB Mass Storage boot application or return.
       
   135 	if ((LoadDevice==ELoadUSBMS) || (LoadDevice==EBootUSBMS))
       
   136 		TryUSBMS();
       
   137 #endif
       
   138 
       
   139 	// Start the menu UI thread, this will cause a console to overwrite the framebuffer
       
   140 	StartMenu();
       
   141 	ClearScreen();
       
   142 
       
   143 	PrintToScreen(_L("Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).\r\n"));
       
   144 	PrintToScreen(_L("BootLoader %d.%d\r\n"), BOOTLDR_VERSION_MAJOR, BOOTLDR_VERSION_MINOR);
       
   145 	PrintToScreen(_L("Platform build %d\n\rBuilt: %s\r\n"), PLATFORM_BUILD, __WDATE__);
       
   146 
       
   147 	// Load Ethernet driver:  it might need to load to set the MAC address in HAL
       
   148     TInt pddLoaded = KErrUnknown;
       
   149 	TInt lddLoaded = KErrUnknown;
       
   150 	TInt opened    = KErrUnknown;
       
   151 	RBusDevEthernet card;
       
   152 
       
   153     pddLoaded = User::LoadPhysicalDevice(PDD_NAME);
       
   154 	if (pddLoaded == KErrNone)
       
   155 		{
       
   156 		lddLoaded = User::LoadLogicalDevice(LDD_NAME);
       
   157 		if (lddLoaded == KErrNone)
       
   158 			{
       
   159 			opened = card.Open(0);
       
   160 			User::After(2000);
       
   161 			}
       
   162 		}
       
   163 
       
   164 	TInt serialNum;
       
   165 	r = HAL::Get(HAL::ESerialNumber, serialNum);
       
   166 
       
   167 	if (r == KErrNone && serialNum != 0)
       
   168 		{
       
   169 		// we only show the serial number if it was available from HAL and set to something
       
   170 		PrintToScreen(_L("MAC Address: 00-0a-%02x-%02x-%02x-%02x\r\n"),
       
   171 			(serialNum & 0xFF000000) >> 24,
       
   172 			(serialNum & 0x00FF0000) >> 16,
       
   173 			(serialNum & 0x0000FF00) >>  8,
       
   174 			(serialNum & 0x000000FF)
       
   175 			);
       
   176 		}
       
   177 
       
   178 
       
   179 	// Free the Ethernet driver now we're done getting the MAC address
       
   180 	if (opened == KErrNone)
       
   181 		{
       
   182 		card.Close();
       
   183 		}
       
   184 	if (lddLoaded == KErrNone)
       
   185 		{
       
   186 	    User::FreeLogicalDevice(LDD_NAME);
       
   187 		}
       
   188 	if (pddLoaded == KErrNone)
       
   189 		{
       
   190 	    User::FreePhysicalDevice(PDD_NAME);
       
   191 		}
       
   192 
       
   193 	if (LoadDevice == EBootEMMC)
       
   194 		{
       
   195 		if ( SearchDrivesRaw() )
       
   196 			{
       
   197 			DoDownload();
       
   198 			}
       
   199 		}
       
   200 		
       
   201 #ifdef __USE_LOCAL_DRIVES__
       
   202 	// The next method to test is reading an image file from removable media
       
   203 	if (SearchDrives())
       
   204 		DoDownload();
       
   205 #endif
       
   206 
       
   207 	// The last method is to attempt to download an image over the serial port
       
   208 	switch (SerialBaud)
       
   209 		{
       
   210 		case EBps115200:
       
   211 			PrintToScreen(_L("Initiating YModem-G on port %d @ 115200 baud\r\n"), SerialDownloadPort);
       
   212 			break;
       
   213 		case EBps230400:
       
   214 			PrintToScreen(_L("Initiating YModem-G on port %d @ 230400 baud\r\n"), SerialDownloadPort);
       
   215 			break;
       
   216 		default:
       
   217 			PrintToScreen(_L("Initiating YModem-G download on port %d\r\n"), SerialDownloadPort);
       
   218 			SerialBaud = EBps115200;
       
   219 			break;
       
   220 		}
       
   221 	r=InitSerialDownload(SerialDownloadPort);
       
   222 	if (r!=KErrNone)
       
   223 		{
       
   224 		RDebug::Print(_L("FAULT: YModem-G download returned %d\r\n"),r);
       
   225 		BOOT_FAULT();
       
   226 		}
       
   227 
       
   228 	PrintToScreen(_L("Receiving %lS\r\nSize %d\r\n"),&FileName,FileSize);
       
   229 	DoDownload();
       
   230 }
       
   231 
       
   232 TUint Check(const TUint32* aPtr, TInt aSize)
       
   233 	{
       
   234 	TUint sum=0;
       
   235 	aSize/=4;
       
   236 	while (aSize-->0)
       
   237 		sum+=*aPtr++;
       
   238 	return sum;
       
   239 	}
       
   240 
       
   241 TUint CheckSumRom()
       
   242 	{
       
   243 #if 0
       
   244 	//
       
   245 	// This code was obtained from t_romchk in the e32tests, it was useful for
       
   246 	// checking that roms were not getting corrupted during the download
       
   247 	// process.
       
   248 	//
       
   249 	// However, it is not a universal checksum and is not suitable for all
       
   250 	// types of images it is therefore being disabled until we need it again.
       
   251 	//
       
   252 
       
   253 	PrintToScreen(_L("Checking ROM contents...\r\n"));
       
   254 
       
   255 	const TRomHeader* romHdr = (const TRomHeader*)DestinationAddress();
       
   256 	TInt size = romHdr->iUnpagedUncompressedSize;
       
   257 	const TUint32* addr = (TUint32*)romHdr;
       
   258 	PrintToScreen(_L("ROM at %x, size %x\r\n"),addr,size);
       
   259 
       
   260 	TUint checkSum = Check(addr,size);
       
   261 
       
   262 	// hack the checksum because ROMBUILD is broken
       
   263 	checkSum -= (romHdr->iRomSize-size)/4; // adjust for missing 0xffffffff
       
   264 	checkSum -= romHdr->iCompressionType;
       
   265 	checkSum -= romHdr->iUnpagedCompressedSize;
       
   266 	checkSum -= romHdr->iUnpagedUncompressedSize;
       
   267 
       
   268 	TUint expectedChecksum = 0x12345678;
       
   269 	if (checkSum != expectedChecksum)
       
   270 		{
       
   271 		PrintToScreen(_L("Fail: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
       
   272 		RDebug::Print(_L("Fail: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
       
   273 		BOOT_FAULT();
       
   274 		}
       
   275 	else
       
   276 		{
       
   277 		PrintToScreen(_L("Pass: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
       
   278 		RDebug::Print(_L("Pass: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
       
   279 		}
       
   280 #endif
       
   281 	return 0;
       
   282 	}
       
   283 
       
   284 
       
   285 GLDEF_C void DoDownload()
       
   286 /*
       
   287  The DoDownload method is ultimatly called by all the download routines, it is
       
   288  responsible for unzipping images as well as stripping off EPOC headers and
       
   289  starting the flash writing methods.
       
   290  */
       
   291 	{
       
   292 	TInt r;
       
   293 
       
   294 	// If the image is zipped start the unzip thread
       
   295 	if (ImageZip)
       
   296 		{
       
   297 		// initialise unzip
       
   298 		PrintToScreen(_L("Loading zip ..\r\n"));
       
   299 		r=DoZipDownload(bootFile);
       
   300 		if (r!=KErrNone)
       
   301 			{
       
   302 			PrintToScreen(_L("\r\nFAULT due to zip %d\r\n"), r);
       
   303 			BOOT_FAULT();
       
   304 			}
       
   305 		PrintToScreen(_L("\r\nZip download complete.\r\n"));
       
   306 		}
       
   307 	else
       
   308 		{
       
   309 		LoadSize=FileSize;
       
   310 				
       
   311 		if( ImageDeflated )
       
   312     		{
       
   313     		PrintToScreen(_L("\r\n\r\nLoading deflated image...\r\n"));
       
   314     	    ImageHeaderPresent=EFalse;
       
   315     	    DoDeflateDownload();
       
   316     	    PrintToScreen(_L("Deflated image download complete.\r\n"));	  
       
   317     		}
       
   318 		else
       
   319     		{
       
   320     		// If it isn't a zipped or deflated image then the filesize is the image size -
       
   321     		// check that it is valid for a Symbian image and determine whether to
       
   322     		// remove any header that may be present.
       
   323     		TInt size_mod_4k=FileSize & 0xfff;
       
   324     		if (size_mod_4k==0)
       
   325     			{
       
   326     			ImageHeaderPresent=EFalse;
       
   327     			PrintToScreen(_L("Image header not present.\r\n"));
       
   328     			}
       
   329     		else if (size_mod_4k==256)
       
   330     			{
       
   331     			ImageHeaderPresent=ETrue;
       
   332     			PrintToScreen(_L("Image header present.\r\n"));
       
   333     			}
       
   334     		else
       
   335     			{
       
   336     		    PrintToScreen(_L("\r\n\r\nInvalid size\r\n"));
       
   337     			BOOT_FAULT();	
       
   338     			}
       
   339     		ImageSize=ImageHeaderPresent ? LoadSize-256 : LoadSize;
       
   340     		TUint8* pD=(TUint8*)DestinationAddress();
       
   341     		TInt block_size;
       
   342     		if (FileSize==0)
       
   343     			block_size=0x1000;		// YModem download with unknown size
       
   344     		else
       
   345     			block_size=Max(0x1000,FileSize>>8);
       
   346     		block_size=(block_size+0xfff)&~0xfff;
       
   347     		if (FileSize>0)
       
   348     			InitProgressBar(0,(TUint)FileSize,_L("LOAD"));
       
   349     		r=KErrNone;
       
   350 
       
   351 // If target location is flash start the flasher thread
       
   352 #ifdef __SUPPORT_FLASH_REPRO__
       
   353     		if (LoadToFlash)
       
   354     			{
       
   355     			r=InitFlashWrite();
       
   356     			if (r!=KErrNone)
       
   357     				{
       
   358     				PrintToScreen(_L("FAULT due to InitFlashWrite return %d\r\n"), r);
       
   359     				BOOT_FAULT();
       
   360     				}
       
   361     			}
       
   362 #endif
       
   363 
       
   364     		while (r==KErrNone)
       
   365     			{
       
   366     			TInt len=block_size;
       
   367     			r=ReadInputData(pD,len);
       
   368 
       
   369     			if (r!=KErrNone && r!=KErrEof)
       
   370     				break;
       
   371     			pD+=len;
       
   372     			ImageReadProgress+=len;
       
   373     			if (FileSize>0)
       
   374     				{
       
   375     				UpdateProgressBar(0,(TUint)ImageReadProgress);
       
   376 				}
       
   377 #ifdef __SUPPORT_FLASH_REPRO__
       
   378     			if (LoadToFlash)
       
   379     				NotifyDataAvailable(ImageReadProgress);
       
   380 #endif
       
   381     			}
       
   382 
       
   383     		if (r!=KErrEof)	
       
   384     			{
       
   385     			PrintToScreen(_L("FAULT due to EOF. %d bytes read.\r\n"), ImageReadProgress);
       
   386     			BOOT_FAULT();
       
   387     			}
       
   388     		else
       
   389     			PrintToScreen(_L("Loaded %d bytes.\r\n"), ImageReadProgress);
       
   390 
       
   391     		if (ImageReadProgress < LoadSize)
       
   392     			ImageSize=ImageHeaderPresent ? ImageReadProgress-256 : ImageReadProgress;
       
   393 #ifdef __SUPPORT_FLASH_REPRO__
       
   394     		if (LoadToFlash)
       
   395     			NotifyDownloadComplete();
       
   396 #endif
       
   397     		}
       
   398 
       
   399 		}
       
   400 	if (CloseInputFunction)
       
   401 		CloseInput();
       
   402 
       
   403 	if (LoadToFlash)
       
   404 		{
       
   405 		// In the load to flash scenario it will boot the image.
       
   406 		while(1)
       
   407 			User::After(10000000);
       
   408 		}
       
   409 
       
   410 	// Booting from Ram - remove the header
       
   411 	if (ImageHeaderPresent)
       
   412 		{
       
   413 		TUint8* pI=(TUint8*)DestinationAddress();
       
   414 		Mem::Move(pI,pI+256,ImageSize);
       
   415 		}
       
   416 
       
   417 	CheckSumRom();
       
   418 
       
   419 	PrintToScreen(_L("Booting Image...\r\n"));
       
   420 	// Restart board with "boot image + located in ram"
       
   421 
       
   422 	User::After(WAIT_TO_REBOOT);
       
   423 		
       
   424 
       
   425 	HAL::Set(HAL::EDisplayState, 0);
       
   426 	Restart(KtRestartReasonBootRestart | KtRestartReasonRAMImage);
       
   427 
       
   428 	//  *** NOTREACHED ***
       
   429 	}
       
   430 
       
   431 GLDEF_C TInt E32Main()
       
   432 	{
       
   433 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   434 
       
   435 	// Make bootloader panics fault the system. This means that this process
       
   436 	// will NEVER END
       
   437 	User::SetCritical(User::ESystemPermanent);
       
   438 
       
   439 	TRAPD(error,RunAppL());
       
   440 	__ASSERT_ALWAYS(!error, User::Panic(KPanicText, error));
       
   441 	
       
   442 	delete cleanup;
       
   443 
       
   444 	PrintToScreen(_L("Boot loader ended abnormally")); 
       
   445 
       
   446 	Ldd.Close();
       
   447 	return 0;
       
   448 	}
       
   449