--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/brdbootldr/ubootldr/main.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,449 @@
+// 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>
+#include <e32rom.h>
+
+#include <hal.h>
+#include <d32ethernet.h>
+
+#define FILE_ID 0x594D555D
+#include "bootldr.h"
+#include "ubootldrldd.h"
+
+#include <d32comm.h>
+
+#ifdef _DEBUG_CORELDR_
+#define WAIT_TO_REBOOT 10000000
+#else
+#define WAIT_TO_REBOOT 100000
+#endif
+
+#define addr_to_page(a) (a&~(0x1000-1))
+
+_LIT(KPanicText,"UBOOTLDR");
+_LIT(LDD_NAME, "Enet");
+_LIT(PDD_NAME, "Ethernet");
+
+// Memory
+RUBootldrLdd Ldd;
+RChunk TheRamChunk; // This is the download area
+
+/// Global number of seconds to delay before reboot
+
+void GetChunk()
+ {
+ TInt PageSize;
+ UserHal::PageSizeInBytes(PageSize);
+
+ TInt r = User::LoadLogicalDevice(KBootldrLddName);
+
+ r = Ldd.Open();
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("FAULT due to LDD open\r\n"));
+ BOOT_FAULT();
+ }
+
+ TUint8* kernelAddress;
+ r=Ldd.CreateChunk(KRamTargetSize,(TAny**)&kernelAddress);
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("FAULT due to chunk create\r\n"));
+ BOOT_FAULT();
+ }
+
+ r = Ldd.CommitMemory(KRamTargetSize,addr_to_page(KRamTargetAddr));
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("FAULT due to commit\r\n"));
+ BOOT_FAULT();
+ }
+
+ r = Ldd.GetChunkHandle(TheRamChunk);
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("FAULT due to handle\r\n"));
+ BOOT_FAULT();
+ }
+
+ TUint8* Base = TheRamChunk.Base();
+ ActualDestinationAddress = (TUint32*)Base;
+ }
+
+// method of getting the date string at build time
+// Taken from e32test\device\t_usbco22.cpp
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+#define __WDATE__ WIDEN(__DATE__)
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Application entry point
+//
+//////////////////////////////////////////////////////////////////////////////
+LOCAL_C void RunAppL()
+ {
+ TInt r;
+
+ // Get the memory download area mapped into a chunk
+ GetChunk();
+
+ // Initialise our graphical screen
+ InitDisplay();
+
+#ifdef __USE_VARIANT_INIT__
+ // The variant initialisation function is likely to perform bootloader
+ // configuration or print debug information.
+ VariantInit();
+#endif
+
+#ifdef __USE_USBMS__
+ // If the bootloader is in the USB Mass Storage mode (indicated by the Variant
+ // initialisation routine) then call that method first; it will either read/boot
+ // an image, start the USB Mass Storage boot application or return.
+ if ((LoadDevice==ELoadUSBMS) || (LoadDevice==EBootUSBMS))
+ TryUSBMS();
+#endif
+
+ // Start the menu UI thread, this will cause a console to overwrite the framebuffer
+ StartMenu();
+ ClearScreen();
+
+ PrintToScreen(_L("Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).\r\n"));
+ PrintToScreen(_L("BootLoader %d.%d\r\n"), BOOTLDR_VERSION_MAJOR, BOOTLDR_VERSION_MINOR);
+ PrintToScreen(_L("Platform build %d\n\rBuilt: %s\r\n"), PLATFORM_BUILD, __WDATE__);
+
+ // Load Ethernet driver: it might need to load to set the MAC address in HAL
+ TInt pddLoaded = KErrUnknown;
+ TInt lddLoaded = KErrUnknown;
+ TInt opened = KErrUnknown;
+ RBusDevEthernet card;
+
+ pddLoaded = User::LoadPhysicalDevice(PDD_NAME);
+ if (pddLoaded == KErrNone)
+ {
+ lddLoaded = User::LoadLogicalDevice(LDD_NAME);
+ if (lddLoaded == KErrNone)
+ {
+ opened = card.Open(0);
+ User::After(2000);
+ }
+ }
+
+ TInt serialNum;
+ r = HAL::Get(HAL::ESerialNumber, serialNum);
+
+ if (r == KErrNone && serialNum != 0)
+ {
+ // we only show the serial number if it was available from HAL and set to something
+ PrintToScreen(_L("MAC Address: 00-0a-%02x-%02x-%02x-%02x\r\n"),
+ (serialNum & 0xFF000000) >> 24,
+ (serialNum & 0x00FF0000) >> 16,
+ (serialNum & 0x0000FF00) >> 8,
+ (serialNum & 0x000000FF)
+ );
+ }
+
+
+ // Free the Ethernet driver now we're done getting the MAC address
+ if (opened == KErrNone)
+ {
+ card.Close();
+ }
+ if (lddLoaded == KErrNone)
+ {
+ User::FreeLogicalDevice(LDD_NAME);
+ }
+ if (pddLoaded == KErrNone)
+ {
+ User::FreePhysicalDevice(PDD_NAME);
+ }
+
+ if (LoadDevice == EBootEMMC)
+ {
+ if ( SearchDrivesRaw() )
+ {
+ DoDownload();
+ }
+ }
+
+#ifdef __USE_LOCAL_DRIVES__
+ // The next method to test is reading an image file from removable media
+ if (SearchDrives())
+ DoDownload();
+#endif
+
+ // The last method is to attempt to download an image over the serial port
+ switch (SerialBaud)
+ {
+ case EBps115200:
+ PrintToScreen(_L("Initiating YModem-G on port %d @ 115200 baud\r\n"), SerialDownloadPort);
+ break;
+ case EBps230400:
+ PrintToScreen(_L("Initiating YModem-G on port %d @ 230400 baud\r\n"), SerialDownloadPort);
+ break;
+ default:
+ PrintToScreen(_L("Initiating YModem-G download on port %d\r\n"), SerialDownloadPort);
+ SerialBaud = EBps115200;
+ break;
+ }
+ r=InitSerialDownload(SerialDownloadPort);
+ if (r!=KErrNone)
+ {
+ RDebug::Print(_L("FAULT: YModem-G download returned %d\r\n"),r);
+ BOOT_FAULT();
+ }
+
+ PrintToScreen(_L("Receiving %lS\r\nSize %d\r\n"),&FileName,FileSize);
+ DoDownload();
+}
+
+TUint Check(const TUint32* aPtr, TInt aSize)
+ {
+ TUint sum=0;
+ aSize/=4;
+ while (aSize-->0)
+ sum+=*aPtr++;
+ return sum;
+ }
+
+TUint CheckSumRom()
+ {
+#if 0
+ //
+ // This code was obtained from t_romchk in the e32tests, it was useful for
+ // checking that roms were not getting corrupted during the download
+ // process.
+ //
+ // However, it is not a universal checksum and is not suitable for all
+ // types of images it is therefore being disabled until we need it again.
+ //
+
+ PrintToScreen(_L("Checking ROM contents...\r\n"));
+
+ const TRomHeader* romHdr = (const TRomHeader*)DestinationAddress();
+ TInt size = romHdr->iUnpagedUncompressedSize;
+ const TUint32* addr = (TUint32*)romHdr;
+ PrintToScreen(_L("ROM at %x, size %x\r\n"),addr,size);
+
+ TUint checkSum = Check(addr,size);
+
+ // hack the checksum because ROMBUILD is broken
+ checkSum -= (romHdr->iRomSize-size)/4; // adjust for missing 0xffffffff
+ checkSum -= romHdr->iCompressionType;
+ checkSum -= romHdr->iUnpagedCompressedSize;
+ checkSum -= romHdr->iUnpagedUncompressedSize;
+
+ TUint expectedChecksum = 0x12345678;
+ if (checkSum != expectedChecksum)
+ {
+ PrintToScreen(_L("Fail: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
+ RDebug::Print(_L("Fail: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
+ BOOT_FAULT();
+ }
+ else
+ {
+ PrintToScreen(_L("Pass: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
+ RDebug::Print(_L("Pass: Checksum = %8x, expected %8x\r\n"),checkSum,expectedChecksum);
+ }
+#endif
+ return 0;
+ }
+
+
+GLDEF_C void DoDownload()
+/*
+ The DoDownload method is ultimatly called by all the download routines, it is
+ responsible for unzipping images as well as stripping off EPOC headers and
+ starting the flash writing methods.
+ */
+ {
+ TInt r;
+
+ // If the image is zipped start the unzip thread
+ if (ImageZip)
+ {
+ // initialise unzip
+ PrintToScreen(_L("Loading zip ..\r\n"));
+ r=DoZipDownload(bootFile);
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("\r\nFAULT due to zip %d\r\n"), r);
+ BOOT_FAULT();
+ }
+ PrintToScreen(_L("\r\nZip download complete.\r\n"));
+ }
+ else
+ {
+ LoadSize=FileSize;
+
+ if( ImageDeflated )
+ {
+ PrintToScreen(_L("\r\n\r\nLoading deflated image...\r\n"));
+ ImageHeaderPresent=EFalse;
+ DoDeflateDownload();
+ PrintToScreen(_L("Deflated image download complete.\r\n"));
+ }
+ else
+ {
+ // If it isn't a zipped or deflated image then the filesize is the image size -
+ // check that it is valid for a Symbian image and determine whether to
+ // remove any header that may be present.
+ TInt size_mod_4k=FileSize & 0xfff;
+ if (size_mod_4k==0)
+ {
+ ImageHeaderPresent=EFalse;
+ PrintToScreen(_L("Image header not present.\r\n"));
+ }
+ else if (size_mod_4k==256)
+ {
+ ImageHeaderPresent=ETrue;
+ PrintToScreen(_L("Image header present.\r\n"));
+ }
+ else
+ {
+ PrintToScreen(_L("\r\n\r\nInvalid size\r\n"));
+ BOOT_FAULT();
+ }
+ ImageSize=ImageHeaderPresent ? LoadSize-256 : LoadSize;
+ TUint8* pD=(TUint8*)DestinationAddress();
+ TInt block_size;
+ if (FileSize==0)
+ block_size=0x1000; // YModem download with unknown size
+ else
+ block_size=Max(0x1000,FileSize>>8);
+ block_size=(block_size+0xfff)&~0xfff;
+ if (FileSize>0)
+ InitProgressBar(0,(TUint)FileSize,_L("LOAD"));
+ r=KErrNone;
+
+// If target location is flash start the flasher thread
+#ifdef __SUPPORT_FLASH_REPRO__
+ if (LoadToFlash)
+ {
+ r=InitFlashWrite();
+ if (r!=KErrNone)
+ {
+ PrintToScreen(_L("FAULT due to InitFlashWrite return %d\r\n"), r);
+ BOOT_FAULT();
+ }
+ }
+#endif
+
+ while (r==KErrNone)
+ {
+ TInt len=block_size;
+ r=ReadInputData(pD,len);
+
+ if (r!=KErrNone && r!=KErrEof)
+ break;
+ pD+=len;
+ ImageReadProgress+=len;
+ if (FileSize>0)
+ {
+ UpdateProgressBar(0,(TUint)ImageReadProgress);
+ }
+#ifdef __SUPPORT_FLASH_REPRO__
+ if (LoadToFlash)
+ NotifyDataAvailable(ImageReadProgress);
+#endif
+ }
+
+ if (r!=KErrEof)
+ {
+ PrintToScreen(_L("FAULT due to EOF. %d bytes read.\r\n"), ImageReadProgress);
+ BOOT_FAULT();
+ }
+ else
+ PrintToScreen(_L("Loaded %d bytes.\r\n"), ImageReadProgress);
+
+ if (ImageReadProgress < LoadSize)
+ ImageSize=ImageHeaderPresent ? ImageReadProgress-256 : ImageReadProgress;
+#ifdef __SUPPORT_FLASH_REPRO__
+ if (LoadToFlash)
+ NotifyDownloadComplete();
+#endif
+ }
+
+ }
+ if (CloseInputFunction)
+ CloseInput();
+
+ if (LoadToFlash)
+ {
+ // In the load to flash scenario it will boot the image.
+ while(1)
+ User::After(10000000);
+ }
+
+ // Booting from Ram - remove the header
+ if (ImageHeaderPresent)
+ {
+ TUint8* pI=(TUint8*)DestinationAddress();
+ Mem::Move(pI,pI+256,ImageSize);
+ }
+
+ CheckSumRom();
+
+ PrintToScreen(_L("Booting Image...\r\n"));
+ // Restart board with "boot image + located in ram"
+
+ User::After(WAIT_TO_REBOOT);
+
+
+ HAL::Set(HAL::EDisplayState, 0);
+ Restart(KtRestartReasonBootRestart | KtRestartReasonRAMImage);
+
+ // *** NOTREACHED ***
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+
+ // Make bootloader panics fault the system. This means that this process
+ // will NEVER END
+ User::SetCritical(User::ESystemPermanent);
+
+ TRAPD(error,RunAppL());
+ __ASSERT_ALWAYS(!error, User::Panic(KPanicText, error));
+
+ delete cleanup;
+
+ PrintToScreen(_L("Boot loader ended abnormally"));
+
+ Ldd.Close();
+ return 0;
+ }
+