os/kernelhwsrv/brdbootldr/ubootldr/main.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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