Merge branch 'master' into app-list-itemsize
[kugel-rb.git] / bootloader / ipodnano2g.c
blobbe714c6273cd2575abbd903e4531dbfc1e343e53
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
27 #include "config.h"
29 #include "inttypes.h"
30 #include "cpu.h"
31 #include "system.h"
32 #include "lcd.h"
33 #include "i2c-s5l8700.h"
34 #include "kernel.h"
35 #include "thread.h"
36 #include "storage.h"
37 #include "fat.h"
38 #include "disk.h"
39 #include "font.h"
40 #include "backlight.h"
41 #include "backlight-target.h"
42 #include "button.h"
43 #include "panic.h"
44 #include "power.h"
45 #include "file.h"
46 #include "common.h"
47 #include "version.h"
49 /* Safety measure - maximum allowed firmware image size.
50 The largest known current (October 2009) firmware is about 6.2MB so
51 we set this to 8MB.
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;
58 extern int line;
60 void fatal_error(void)
62 extern int line;
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");
69 lcd_update();
71 while (1) {
72 if (button_hold() != holdstatus) {
73 if (button_hold()) {
74 holdstatus=true;
75 lcd_puts(0, line, "Hold switch on!");
76 } else {
77 holdstatus=false;
78 lcd_puts(0, line, " ");
80 lcd_update();
85 static void aes_decrypt(void* data, uint32_t size)
87 uint32_t ptr, i;
88 uint32_t go = 1;
90 PWRCONEXT &= ~0x400;
91 AESTYPE = 1;
92 AESUNKREG0 = 1;
93 AESUNKREG0 = 0;
94 AESCONTROL = 1;
95 AESKEYLEN = 8;
96 AESOUTSIZE = size;
97 AESAUXSIZE = 0x10;
98 AESINSIZE = 0x10;
99 AESSIZE3 = 0x10;
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);
105 AESSTATUS = 6;
106 AESGO = go;
107 go = 3;
108 while ((AESSTATUS & 6) == 0);
109 if (ptr == 0) break;
110 for (i = 0; i < 4; i++)
111 ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
113 AESCONTROL = 0;
114 PWRCONEXT |= 0x400;
117 static int readfw(char* filename, void* address, int* size)
119 int i;
120 uint32_t startsector = 0;
121 uint32_t buffer[0x200];
123 if (nand_read_sectors(0, 1, buffer) != 0)
124 return -1;
126 if (*((uint16_t*)((uint32_t)buffer + 0x1FE)) != 0xAA55)
127 return -2;
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);
133 break;
137 if (startsector == 0)
138 return -3;
140 if (nand_read_sectors(startsector, 1, buffer) != 0)
141 return -4;
143 if (buffer[0x40] != 0x5B68695D)
144 return -5;
146 if (nand_read_sectors(startsector + 1 + (buffer[0x41] >> 11), 1, buffer) != 0)
147 return -6;
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)
155 return -7;
157 /* Success! */
158 return 0;
162 /* Nothing found */
163 return -8;
166 void main(void)
168 int i;
169 int btn;
170 int size;
171 int rc;
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();
179 system_init();
180 kernel_init();
182 i2c_init();
184 enable_irq();
186 backlight_init(); /* Turns on the backlight */
188 lcd_init();
189 font_init();
191 lcd_set_foreground(LCD_WHITE);
192 lcd_set_background(LCD_BLACK);
193 lcd_clear_display();
195 button_init();
197 btn = button_status();
199 /* Enable bootloader messages */
200 if (btn==BUTTON_RIGHT)
201 verbose = true;
203 lcd_setfont(FONT_SYSFIXED);
205 printf("Rockbox boot loader");
206 printf("Version: " RBVERSION);
208 i = storage_init();
210 if (i != 0) {
211 printf("ATA error: %d", i);
212 fatal_error();
215 disk_init();
216 rc = disk_mount_all();
217 if (rc<=0)
219 printf("No partition found");
220 fatal_error();
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);
230 fatal_error();
233 /* Now we need to decrypt it */
234 printf("Decrypting %d bytes...",size);
236 aes_decrypt(loadbuffer, size);
237 } else {
238 printf("Loading Rockbox...");
239 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
241 if (rc != EOK) {
242 printf("Error!");
243 printf("Can't load " BOOTFILE ": ");
244 printf(strerror(rc));
245 fatal_error();
248 printf("Rockbox loaded.");
252 /* If we get here, we have a new firmware image at 0x08000000, run it */
253 printf("Executing...");
255 disable_irq();
257 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves
260 MIUCON &= ~1;
262 /* Disable caches and protection unit */
263 asm volatile(
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");