1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 by Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
33 #include "i2c-s5l8700.h"
40 #include "backlight.h"
41 #include "backlight-target.h"
49 /* Safety measure - maximum allowed firmware image size.
50 The largest known current (October 2009) firmware is about 6.2MB so
53 #define MAX_LOADSIZE (8*1024*1024)
55 /* The buffer to load the firmware into - use an uncached alias of 0x08000000 */
56 unsigned char *loadbuffer
= (unsigned char *)0x48000000;
60 void fatal_error(void)
63 bool holdstatus
=false;
65 /* System font is 6 pixels wide */
66 printf("Hold MENU+SELECT to");
67 printf("reboot then SELECT+PLAY");
68 printf("for disk mode");
72 if (button_hold() != holdstatus
) {
75 lcd_puts(0, line
, "Hold switch on!");
78 lcd_puts(0, line
, " ");
85 static void aes_decrypt(void* data
, uint32_t size
)
100 for (ptr
= (size
>> 2) - 4; ; ptr
-= 4)
102 AESOUTADDR
= (uint32_t)data
+ (ptr
<< 2);
103 AESINADDR
= (uint32_t)data
+ (ptr
<< 2);
104 AESAUXADDR
= (uint32_t)data
+ (ptr
<< 2);
108 while ((AESSTATUS
& 6) == 0);
110 for (i
= 0; i
< 4; i
++)
111 ((uint32_t*)data
)[ptr
+ i
] ^= ((uint32_t*)data
)[ptr
+ i
- 4];
117 static int readfw(char* filename
, void* address
, int* size
)
120 uint32_t startsector
= 0;
121 uint32_t buffer
[0x200];
123 if (nand_read_sectors(0, 1, buffer
) != 0)
126 if (*((uint16_t*)((uint32_t)buffer
+ 0x1FE)) != 0xAA55)
129 for (i
= 0x1C2; i
< 0x200; i
+= 0x10) {
130 if (((uint8_t*)buffer
)[i
] == 0) {
131 startsector
= *((uint16_t*)((uint32_t)buffer
+ i
+ 4))
132 | (*((uint16_t*)((uint32_t)buffer
+ i
+ 6)) << 16);
137 if (startsector
== 0)
140 if (nand_read_sectors(startsector
, 1, buffer
) != 0)
143 if (buffer
[0x40] != 0x5B68695D)
146 if (nand_read_sectors(startsector
+ 1 + (buffer
[0x41] >> 11), 1, buffer
) != 0)
149 for (i
= 0; i
< 0x1FE; i
+= 10) {
150 if (memcmp(&buffer
[i
], filename
, 8) == 0) {
151 uint32_t filesector
= startsector
+ 1 + (buffer
[i
+ 3] >> 11);
152 *size
= buffer
[i
+ 4];
154 if (nand_read_sectors(filesector
, ((*size
+ 0x7FF) >> 11), address
) != 0)
172 bool button_was_held
;
174 /* Check the button hold status as soon as possible - to
175 give the user maximum chance to turn it on in order to
176 reset the settings in rockbox. */
177 button_was_held
= button_hold();
186 backlight_init(); /* Turns on the backlight */
191 lcd_set_foreground(LCD_WHITE
);
192 lcd_set_background(LCD_BLACK
);
197 btn
= button_status();
199 /* Enable bootloader messages */
200 if (btn
==BUTTON_RIGHT
)
203 lcd_setfont(FONT_SYSFIXED
);
205 printf("Rockbox boot loader");
206 printf("Version: " RBVERSION
);
211 printf("ATA error: %d", i
);
216 rc
= disk_mount_all();
219 printf("No partition found");
223 if (button_was_held
|| (btn
==BUTTON_MENU
)) {
224 /* If either the hold switch was on, or the Menu button was held, then
225 try the Apple firmware */
226 printf("Loading original firmware...");
228 if ((rc
= readfw("DNANkbso", loadbuffer
, &size
)) < 0) {
229 printf("readfw error %d",rc
);
233 /* Now we need to decrypt it */
234 printf("Decrypting %d bytes...",size
);
236 aes_decrypt(loadbuffer
, size
);
238 printf("Loading Rockbox...");
239 rc
=load_firmware(loadbuffer
, BOOTFILE
, MAX_LOADSIZE
);
243 printf("Can't load " BOOTFILE
": ");
244 printf(strerror(rc
));
248 printf("Rockbox loaded.");
252 /* If we get here, we have a new firmware image at 0x08000000, run it */
253 printf("Executing...");
257 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves
262 /* Disable caches and protection unit */
264 "mrc 15, 0, r0, c1, c0, 0 \n"
265 "bic r0, r0, #0x1000 \n"
266 "bic r0, r0, #0x5 \n"
267 "mcr 15, 0, r0, c1, c0, 0 \n"
270 /* Branch to start of DRAM */
271 asm volatile("ldr pc, =0x08000000");