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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // improvised boot loader mechanism
23 #include <e32const_private.h>
25 #include <e32std_private.h>
31 #include "bootloader_variantconfig.h"
32 #include <nkern/nk_trace.h>
37 #include <d32ethernet.h>
39 #define FILE_ID 0x594D555D
41 #include "ubootldrldd.h"
45 #ifdef _DEBUG_CORELDR_
46 #define WAIT_TO_REBOOT 10000000
48 #define WAIT_TO_REBOOT 100000
51 #define addr_to_page(a) (a&~(0x1000-1))
53 _LIT(KPanicText,"UBOOTLDR");
54 _LIT(LDD_NAME, "Enet");
55 _LIT(PDD_NAME, "Ethernet");
59 RChunk TheRamChunk; // This is the download area
61 /// Global number of seconds to delay before reboot
66 UserHal::PageSizeInBytes(PageSize);
68 TInt r = User::LoadLogicalDevice(KBootldrLddName);
73 PrintToScreen(_L("FAULT due to LDD open\r\n"));
77 TUint8* kernelAddress;
78 r=Ldd.CreateChunk(KRamTargetSize,(TAny**)&kernelAddress);
81 PrintToScreen(_L("FAULT due to chunk create\r\n"));
85 r = Ldd.CommitMemory(KRamTargetSize,addr_to_page(KRamTargetAddr));
88 PrintToScreen(_L("FAULT due to commit\r\n"));
92 r = Ldd.GetChunkHandle(TheRamChunk);
95 PrintToScreen(_L("FAULT due to handle\r\n"));
99 TUint8* Base = TheRamChunk.Base();
100 ActualDestinationAddress = (TUint32*)Base;
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__)
110 //////////////////////////////////////////////////////////////////////////////
112 // Application entry point
114 //////////////////////////////////////////////////////////////////////////////
115 LOCAL_C void RunAppL()
119 // Get the memory download area mapped into a chunk
122 // Initialise our graphical screen
125 #ifdef __USE_VARIANT_INIT__
126 // The variant initialisation function is likely to perform bootloader
127 // configuration or print debug information.
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))
139 // Start the menu UI thread, this will cause a console to overwrite the framebuffer
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__);
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;
153 pddLoaded = User::LoadPhysicalDevice(PDD_NAME);
154 if (pddLoaded == KErrNone)
156 lddLoaded = User::LoadLogicalDevice(LDD_NAME);
157 if (lddLoaded == KErrNone)
159 opened = card.Open(0);
165 r = HAL::Get(HAL::ESerialNumber, serialNum);
167 if (r == KErrNone && serialNum != 0)
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)
179 // Free the Ethernet driver now we're done getting the MAC address
180 if (opened == KErrNone)
184 if (lddLoaded == KErrNone)
186 User::FreeLogicalDevice(LDD_NAME);
188 if (pddLoaded == KErrNone)
190 User::FreePhysicalDevice(PDD_NAME);
193 if (LoadDevice == EBootEMMC)
195 if ( SearchDrivesRaw() )
201 #ifdef __USE_LOCAL_DRIVES__
202 // The next method to test is reading an image file from removable media
207 // The last method is to attempt to download an image over the serial port
211 PrintToScreen(_L("Initiating YModem-G on port %d @ 115200 baud\r\n"), SerialDownloadPort);
214 PrintToScreen(_L("Initiating YModem-G on port %d @ 230400 baud\r\n"), SerialDownloadPort);
217 PrintToScreen(_L("Initiating YModem-G download on port %d\r\n"), SerialDownloadPort);
218 SerialBaud = EBps115200;
221 r=InitSerialDownload(SerialDownloadPort);
224 RDebug::Print(_L("FAULT: YModem-G download returned %d\r\n"),r);
228 PrintToScreen(_L("Receiving %lS\r\nSize %d\r\n"),&FileName,FileSize);
232 TUint Check(const TUint32* aPtr, TInt aSize)
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
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.
253 PrintToScreen(_L("Checking ROM contents...\r\n"));
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);
260 TUint checkSum = Check(addr,size);
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;
268 TUint expectedChecksum = 0x12345678;
269 if (checkSum != expectedChecksum)
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);
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);
285 GLDEF_C void DoDownload()
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.
294 // If the image is zipped start the unzip thread
298 PrintToScreen(_L("Loading zip ..\r\n"));
299 r=DoZipDownload(bootFile);
302 PrintToScreen(_L("\r\nFAULT due to zip %d\r\n"), r);
305 PrintToScreen(_L("\r\nZip download complete.\r\n"));
313 PrintToScreen(_L("\r\n\r\nLoading deflated image...\r\n"));
314 ImageHeaderPresent=EFalse;
316 PrintToScreen(_L("Deflated image download complete.\r\n"));
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;
326 ImageHeaderPresent=EFalse;
327 PrintToScreen(_L("Image header not present.\r\n"));
329 else if (size_mod_4k==256)
331 ImageHeaderPresent=ETrue;
332 PrintToScreen(_L("Image header present.\r\n"));
336 PrintToScreen(_L("\r\n\r\nInvalid size\r\n"));
339 ImageSize=ImageHeaderPresent ? LoadSize-256 : LoadSize;
340 TUint8* pD=(TUint8*)DestinationAddress();
343 block_size=0x1000; // YModem download with unknown size
345 block_size=Max(0x1000,FileSize>>8);
346 block_size=(block_size+0xfff)&~0xfff;
348 InitProgressBar(0,(TUint)FileSize,_L("LOAD"));
351 // If target location is flash start the flasher thread
352 #ifdef __SUPPORT_FLASH_REPRO__
358 PrintToScreen(_L("FAULT due to InitFlashWrite return %d\r\n"), r);
367 r=ReadInputData(pD,len);
369 if (r!=KErrNone && r!=KErrEof)
372 ImageReadProgress+=len;
375 UpdateProgressBar(0,(TUint)ImageReadProgress);
377 #ifdef __SUPPORT_FLASH_REPRO__
379 NotifyDataAvailable(ImageReadProgress);
385 PrintToScreen(_L("FAULT due to EOF. %d bytes read.\r\n"), ImageReadProgress);
389 PrintToScreen(_L("Loaded %d bytes.\r\n"), ImageReadProgress);
391 if (ImageReadProgress < LoadSize)
392 ImageSize=ImageHeaderPresent ? ImageReadProgress-256 : ImageReadProgress;
393 #ifdef __SUPPORT_FLASH_REPRO__
395 NotifyDownloadComplete();
400 if (CloseInputFunction)
405 // In the load to flash scenario it will boot the image.
407 User::After(10000000);
410 // Booting from Ram - remove the header
411 if (ImageHeaderPresent)
413 TUint8* pI=(TUint8*)DestinationAddress();
414 Mem::Move(pI,pI+256,ImageSize);
419 PrintToScreen(_L("Booting Image...\r\n"));
420 // Restart board with "boot image + located in ram"
422 User::After(WAIT_TO_REBOOT);
425 HAL::Set(HAL::EDisplayState, 0);
426 Restart(KtRestartReasonBootRestart | KtRestartReasonRAMImage);
428 // *** NOTREACHED ***
431 GLDEF_C TInt E32Main()
433 CTrapCleanup* cleanup=CTrapCleanup::New();
435 // Make bootloader panics fault the system. This means that this process
437 User::SetCritical(User::ESystemPermanent);
439 TRAPD(error,RunAppL());
440 __ASSERT_ALWAYS(!error, User::Panic(KPanicText, error));
444 PrintToScreen(_L("Boot loader ended abnormally"));