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"
48 /* Safety measure - maximum allowed firmware image size.
49 The largest known current (October 2009) firmware is about 6.2MB so
52 #define MAX_LOADSIZE (8*1024*1024)
54 /* The buffer to load the firmware into - use an uncached alias of 0x08000000 */
55 unsigned char *loadbuffer
= (unsigned char *)0x48000000;
57 /* Bootloader version */
58 char version
[] = APPSVERSION
;
62 void fatal_error(void)
65 bool holdstatus
=false;
67 /* System font is 6 pixels wide */
68 printf("Hold MENU+SELECT to");
69 printf("reboot then SELECT+PLAY");
70 printf("for disk mode");
74 if (button_hold() != holdstatus
) {
77 lcd_puts(0, line
, "Hold switch on!");
80 lcd_puts(0, line
, " ");
87 /* aes_decrypt() and readfw() functions taken from iloader - (C)
88 Michael Sparmann and licenced under GPL v2 or later.
91 static void aes_decrypt(void* data
, uint32_t size
)
106 for (ptr
= (size
>> 2) - 4; ; ptr
-= 4)
108 AESOUTADDR
= (uint32_t)data
+ (ptr
<< 2);
109 AESINADDR
= (uint32_t)data
+ (ptr
<< 2);
110 AESAUXADDR
= (uint32_t)data
+ (ptr
<< 2);
114 while ((AESSTATUS
& 6) == 0);
116 for (i
= 0; i
< 4; i
++)
117 ((uint32_t*)data
)[ptr
+ i
] ^= ((uint32_t*)data
)[ptr
+ i
- 4];
123 static int readfw(char* filename
, void* address
, int* size
)
126 uint32_t startsector
= 0;
127 uint32_t buffer
[0x200];
129 if (nand_read_sectors(0, 1, buffer
) != 0)
132 if (*((uint16_t*)((uint32_t)buffer
+ 0x1FE)) != 0xAA55)
135 for (i
= 0x1C2; i
< 0x200; i
+= 0x10) {
136 if (((uint8_t*)buffer
)[i
] == 0) {
137 startsector
= *((uint16_t*)((uint32_t)buffer
+ i
+ 4))
138 | (*((uint16_t*)((uint32_t)buffer
+ i
+ 6)) << 16);
143 if (startsector
== 0)
146 if (nand_read_sectors(startsector
, 1, buffer
) != 0)
149 if (buffer
[0x40] != 0x5B68695D)
152 if (nand_read_sectors(startsector
+ 1 + (buffer
[0x41] >> 11), 1, buffer
) != 0)
155 for (i
= 0; i
< 0x1FE; i
+= 10) {
156 if (memcmp(&buffer
[i
], filename
, 8) == 0) {
157 uint32_t filesector
= startsector
+ 1 + (buffer
[i
+ 3] >> 11);
158 *size
= buffer
[i
+ 4];
160 if (nand_read_sectors(filesector
, ((*size
+ 0x7FF) >> 11), address
) != 0)
178 bool button_was_held
;
180 /* Check the button hold status as soon as possible - to
181 give the user maximum chance to turn it on in order to
182 reset the settings in rockbox. */
183 button_was_held
= button_hold();
192 backlight_init(); /* Turns on the backlight */
197 lcd_set_foreground(LCD_WHITE
);
198 lcd_set_background(LCD_BLACK
);
205 /* Enable bootloader messages */
206 if (btn
==BUTTON_RIGHT
)
209 lcd_setfont(FONT_SYSFIXED
);
211 printf("Rockbox boot loader");
212 printf("Version: %s", version
);
217 printf("ATA error: %d", i
);
222 rc
= disk_mount_all();
225 printf("No partition found");
229 if (button_was_held
|| (btn
==BUTTON_MENU
)) {
230 /* If either the hold switch was on, or the Menu button was held, then
231 try the Apple firmware */
232 printf("Loading original firmware...");
234 if ((rc
= readfw("DNANkbso", loadbuffer
, &size
)) < 0) {
235 printf("readfw error %d",rc
);
239 /* Now we need to decrypt it */
240 printf("Decrypting %d bytes...",size
);
242 aes_decrypt(loadbuffer
, size
);
244 printf("Loading Rockbox...");
245 rc
=load_firmware(loadbuffer
, BOOTFILE
, MAX_LOADSIZE
);
249 printf("Can't load " BOOTFILE
": ");
250 printf(strerror(rc
));
254 printf("Rockbox loaded.");
258 /* If we get here, we have a new firmware image at 0x08000000, run it */
259 printf("Executing...");
263 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves
268 /* Disable caches and protection unit */
270 "mrc 15, 0, r0, c1, c0, 0 \n"
271 "bic r0, r0, #0x1000 \n"
272 "bic r0, r0, #0x5 \n"
273 "mcr 15, 0, r0, c1, c0, 0 \n"
276 /* Branch to start of DRAM */
277 asm volatile("ldr pc, =0x08000000");