1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 by Jörg Hohensohn
12 * Second-level bootloader, with dual-boot feature by holding F1/Menu
13 * This is the image being descrambled and executed by the boot ROM.
14 * It's task is to copy Rockbox from Flash to DRAM.
15 * The image(s) in flash may optionally be compressed with UCL 2e
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
28 #include "bootloader.h"
32 /* start with the vector table */
33 UINT32 vectors
[] __attribute__ ((section (".vectors"))) =
35 (UINT32
)_main
, /* entry point, the copy routine */
36 (UINT32
)(end_stack
- 1), /* initial stack pointer */
37 FLASH_BASE
+ 0x200, /* source of image in flash */
38 (UINT32
)total_size
, /* size of image */
39 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
40 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
41 0x03020080 /* mask and version (just as a suggestion) */
44 /* our binary has to start with a vector to the entry point */
45 tpMain start_vector
[] __attribute__ ((section (".startvector"))) = {main
};
48 #ifdef NO_ROM /* some code which is only needed for the romless variant */
55 asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts
56 asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack
57 asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base
59 /* copy everything to IRAM and continue there */
60 pSrc
= begin_iramcopy
;
62 pEnd
= pDest
+ (begin_stack
- begin_text
);
70 main(); /* jump to the real main() */
76 /* inits from the boot ROM, whether they make sense or not */
77 PBDR
&= 0xFFBF; /* LED off (0x131E) */
78 PBCR2
= 0; /* all GPIO */
79 PBIOR
|= 0x0040; /* LED output */
80 PBIOR
&= 0xFFF1; /* LCD lines input */
82 /* init DRAM like the boot ROM does */
93 #endif /* #ifdef NO_ROM */
100 PlatformInit(); /* model-specific inits */
102 nButton
= ButtonPressed();
105 { /* F3 means start monitor */
111 pImage
= GetStartImage(nButton
); /* which image */
112 DecompressStart(pImage
); /* move into place and start it */
115 return 0; /* I guess we won't return ;-) */
119 /* init code that is specific to certain platform */
120 void PlatformInit(void)
123 BootInit(); /* if not started by boot ROM, we need to init what it did */
126 #if defined PLATFORM_PLAYER
127 BRR1
= 0x19; /* 14400 Baud for monitor */
128 PBDRL
|= 0x10; /* set PB4 to 1 to power the hd early (and prepare for
129 * probing in case the charger is connected) */
130 PBIORL
|= 0x10; /* make PB4 an output */
131 PACR2
&= 0xFFFC; /* GPIO for PA0 (charger detection, input by default) */
132 if (!(PADRL
& 0x01)) /* charger plugged? */
133 { /* we need to probe whether the box is able to control hd power */
136 PBIORL
&= ~0x10; /* set PB4 to input */
137 /* wait whether it goes low, max. ~1 ms */
138 for (i
= 0; (PBDRL
& 0x10) && i
< 1000; i
++);
140 if (~(PBDRL
& 0x10)) /* pulled low -> power controllable */
141 PBDRL
&= 0x10; /* set PB4 low */
142 else /* still floating high -> not controllable */
143 PBDRL
|= 0x10; /* set PB4 high */
144 PBIORL
|= 0x10; /* ..and output again */
146 #elif defined PLATFORM_RECORDER
147 BRR1
= 0x02; /* 115200 Baud for monitor */
148 if (ReadADC(7) > 0x100) /* charger plugged? */
149 { /* switch off the HD, else a flat battery may not start */
150 PACR2
&= 0xFBFF; /* GPIO for PA5 */
151 PAIOR
|= 0x0020; /* make PA5 an output (low by default) */
153 #elif defined PLATFORM_FM
154 BRR1
= 0x02; /* 115200 Baud for monitor */
155 PBDR
|= 0x0020; /* set PB5 to keep power (fixes the ON-holding problem) */
156 PBIOR
|= 0x0020; /* make PB5 an output */
157 if (ReadADC(0) < 0x1FF) /* charger plugged? */
158 { /* switch off the HD, else a flat battery may not start */
159 PACR2
&= 0xFBFF; /* GPIO for PA5 */
160 PAIOR
|= 0x0020; /* make PA5 an output (low by default) */
162 #elif defined PLATFORM_ONDIO
163 BRR1
= 0x19; /* 14400 Baud for monitor */
164 PBDR
|= 0x0020; /* set PB5 to keep power (fixes the ON-holding problem) */
165 PBIOR
|= 0x0020; /* make PB5 an output */
168 /* platform-independent inits */
169 DCR
|= 0x1000; /* enable burst mode on DRAM */
170 BCR
|= 0x2000; /* activate Warp mode (simultaneous internal and external
175 /* Thinned out version of the UCL 2e decompression sourcecode
176 * Original (C) Markus F.X.J Oberhumer under GNU GPL license */
177 #define GETBIT(bb, src, ilen) \
178 (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
180 int ucl_nrv2e_decompress_8(
181 const UINT8
*src
, UINT8
*dst
, UINT32
* dst_len
)
184 unsigned ilen
= 0, olen
= 0, last_m_off
= 1;
188 unsigned m_off
, m_len
;
190 while (GETBIT(bb
,src
,ilen
))
192 dst
[olen
++] = src
[ilen
++];
197 m_off
= m_off
*2 + GETBIT(bb
,src
,ilen
);
198 if (GETBIT(bb
,src
,ilen
)) break;
199 m_off
= (m_off
-1)*2 + GETBIT(bb
,src
,ilen
);
204 m_len
= GETBIT(bb
,src
,ilen
);
208 m_off
= (m_off
-3)*256 + src
[ilen
++];
209 if (m_off
== 0xffffffff)
211 m_len
= (m_off
^ 0xffffffff) & 1;
213 last_m_off
= ++m_off
;
216 m_len
= 1 + GETBIT(bb
,src
,ilen
);
217 else if (GETBIT(bb
,src
,ilen
))
218 m_len
= 3 + GETBIT(bb
,src
,ilen
);
223 m_len
= m_len
*2 + GETBIT(bb
,src
,ilen
);
224 } while (!GETBIT(bb
,src
,ilen
));
227 m_len
+= (m_off
> 0x500);
230 m_pos
= dst
+ olen
- m_off
;
231 dst
[olen
++] = *m_pos
++;
232 do dst
[olen
++] = *m_pos
++; while (--m_len
> 0);
241 /* move the image into place and start it */
242 void DecompressStart(tImage
* pImage
)
247 pSrc
= pImage
->image
;
248 pDest
= pImage
->pDestination
;
250 if (pSrc
!= pDest
) /* if not linked to that flash address */
252 if (pImage
->flags
& IF_UCL_2E
)
253 { /* UCL compressed, algorithm 2e */
254 UINT32 dst_len
; /* dummy */
255 ucl_nrv2e_decompress_8((UINT8
*)pSrc
, (UINT8
*)pDest
, &dst_len
);
258 { /* uncompressed, copy it */
259 UINT32 size
= pImage
->size
;
261 size
= (size
+ 3) / 4; /* round up to 32bit-words */
268 while (pDest
< pEnd
);
276 int ReadADC(int channel
)
278 /* after channel 3, the ports wrap and get re-used */
279 volatile UINT16
* pResult
= (UINT16
*)(ADDRAH_ADDR
+ 2 * (channel
& 0x03));
280 int timeout
= 266; /* conversion takes 266 clock cycles */
282 ADCSR
= 0x20 | channel
; /* start single conversion */
283 while (((ADCSR
& 0x80) == 0) && (--timeout
)); /* 6 instructions per round*/
285 return (timeout
== 0) ? -1 : *pResult
>>6;
290 /* This function is platform-dependent,
291 * until I figure out how to distinguish at runtime. */
292 int ButtonPressed(void) /* return 1,2,3 for F1,F2,F3, 0 if none pressed */
295 int value
= ReadADC(CHANNEL
);
297 if (value
>= F1_LOWER
&& value
<= F1_UPPER
) /* in range */
299 else if (value
>= F2_LOWER
&& value
<= F2_UPPER
) /* in range */
301 else if (value
>= F3_LOWER
&& value
<= F3_UPPER
) /* in range */
306 if (!(value
& F1_MASK
))
308 else if (!(value
& F2_MASK
))
310 else if (!(value
& F3_MASK
))
318 /* Determine the image to be started */
319 tImage
* GetStartImage(int nPreferred
)
322 tImage
* pImage2
= NULL
; /* default to not present */
324 UINT32
* pFlash
= (UINT32
*)FLASH_BASE
;
326 /* determine the first image position */
327 pos
= pFlash
[2] + pFlash
[3]; /* position + size of the bootloader
329 pos
= (pos
+ 3) & ~3; /* be sure it's 32 bit aligned */
331 pImage1
= (tImage
*)pos
;
333 if (pImage1
->size
!= 0)
334 { /* check for second image */
335 pos
= (UINT32
)(&pImage1
->image
) + pImage1
->size
;
336 pImage2
= (tImage
*)pos
;
338 /* does it make sense? (not in FF or 00 erazed space) */
339 if (pImage2
->pDestination
== (void*)0xFFFFFFFF
340 || pImage2
->size
== 0xFFFFFFFF
341 || pImage2
->pExecute
== (void*)0xFFFFFFFF
342 || pImage2
->flags
== 0xFFFFFFFF
343 || pImage2
->pDestination
== NULL
)
344 /* size, execute and flags can legally be 0 */
346 pImage2
= NULL
; /* invalidate */
350 if (pImage2
== NULL
|| nPreferred
== 1)
351 { /* no second image or overridden: return the first */
355 return pImage2
; /* return second image */
358 /* diagnostic functions */
360 void SetLed(BOOL bOn
)
371 PBIOR
&= 0xFBFF; /* input: RXD1 remote pin */
372 PBCR1
|= 0x00A0; /* set PB11+PB10 to UART */
373 PBCR1
&= 0xFFAF; /* clear bits 6, 4 -> UART */
374 SMR1
= 0x00; /* async format 8N1, baud generator input is CPU clock */
375 SCR1
= 0x30; /* transmit+receive enable */
376 PBCR1
&= 0x00FF; /* set bit 12...15 as GPIO */
377 SSR1
&= 0xBF; /* clear bit 6 (RDRF, receive data register full) */
384 while (!(SSR1
& SCI_RDRF
)); /* wait for char to be available */
391 void UartWrite(UINT8 byte
)
393 while (!(SSR1
& SCI_TDRE
)); /* wait for transmit buffer empty */
399 /* include the mini monitor as a rescue feature, started with F3 */
406 volatile UINT8
* paddr
= NULL
;
407 volatile UINT8
* pflash
= NULL
; /* flash base address */
417 content
= UartRead();
418 UartWrite(cmd
); /* acknowledge by returning the command value */
419 while (!(SSR1
& SCI_TEND
)); /* wait for empty shift register,
420 * before changing baudrate */
425 addr
= (UartRead() << 24) | (UartRead() << 16)
426 | (UartRead() << 8) | UartRead();
427 paddr
= (UINT8
*)addr
;
428 pflash
= (UINT8
*)(addr
& 0xFFF80000); /* round down to 512k align*/
429 UartWrite(cmd
); /* acknowledge by returning the command value */
434 UartWrite(content
); /* the content is the ack */
438 content
= UartRead();
440 UartWrite(cmd
); /* acknowledge by returning the command value */
448 UartWrite(content
); /* the content is the ack */
456 content
= UartRead();
459 UartWrite(cmd
); /* acknowledge by returning the command value */
463 content
= UartRead();
464 pflash
[0x5555] = 0xAA; /* set flash to command mode */
465 pflash
[0x2AAA] = 0x55;
466 pflash
[0x5555] = 0xA0; /* byte program command */
468 UartWrite(cmd
); /* acknowledge by returning the command value */
475 content
= UartRead();
476 pflash
[0x5555] = 0xAA; /* set flash to command mode */
477 pflash
[0x2AAA] = 0x55;
478 pflash
[0x5555] = 0xA0; /* byte program command */
481 UartWrite(cmd
); /* acknowledge by returning the command value */
485 content
= *(UINT16
*)paddr
;
487 UartWrite(content
>> 8); /* highbyte */
488 UartWrite(content
& 0xFF); /* lowbyte */
492 content
= UartRead() << 8 | UartRead();
493 *(UINT16
*)paddr
= content
;
495 UartWrite(cmd
); /* acknowledge by returning the command value */
500 tpFunc pFunc
= (tpFunc
)paddr
;
502 UartWrite(cmd
); /* acknowledge by returning the command value*/
507 UartWrite(1); /* return our version number */
513 UartWrite(~cmd
); /* error acknowledge */