author | mikek |
Sun, 27 Jun 2010 21:43:55 +0100 | |
branch | GCC_SURGE |
changeset 181 | bd8f1e65581b |
parent 0 | a41df078684a |
permissions | -rw-r--r-- |
// 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; }