Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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;
}