udelay between command and data write seems to get rid of the display glitches on...
[kugel-rb.git] / bootloader / ipodnano2g.c
blobb2b2138f789bde8b3ceab265141c69b60c7d4914
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 /* aes_decrypt() and readfw() functions taken from iLoader.
86 (C) Michael Sparmann and licenced under GPL v2 or later.
89 static void aes_decrypt(void* data, uint32_t size)
91 uint32_t ptr, i;
92 uint32_t go = 1;
94 PWRCONEXT &= ~0x400;
95 AESTYPE = 1;
96 AESUNKREG0 = 1;
97 AESUNKREG0 = 0;
98 AESCONTROL = 1;
99 AESKEYLEN = 8;
100 AESOUTSIZE = size;
101 AESAUXSIZE = 0x10;
102 AESINSIZE = 0x10;
103 AESSIZE3 = 0x10;
104 for (ptr = (size >> 2) - 4; ; ptr -= 4)
106 AESOUTADDR = (uint32_t)data + (ptr << 2);
107 AESINADDR = (uint32_t)data + (ptr << 2);
108 AESAUXADDR = (uint32_t)data + (ptr << 2);
109 AESSTATUS = 6;
110 AESGO = go;
111 go = 3;
112 while ((AESSTATUS & 6) == 0);
113 if (ptr == 0) break;
114 for (i = 0; i < 4; i++)
115 ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
117 AESCONTROL = 0;
118 PWRCONEXT |= 0x400;
121 static int readfw(char* filename, void* address, int* size)
123 int i;
124 uint32_t startsector = 0;
125 uint32_t buffer[0x200];
127 if (nand_read_sectors(0, 1, buffer) != 0)
128 return -1;
130 if (*((uint16_t*)((uint32_t)buffer + 0x1FE)) != 0xAA55)
131 return -2;
133 for (i = 0x1C2; i < 0x200; i += 0x10) {
134 if (((uint8_t*)buffer)[i] == 0) {
135 startsector = *((uint16_t*)((uint32_t)buffer + i + 4))
136 | (*((uint16_t*)((uint32_t)buffer + i + 6)) << 16);
137 break;
141 if (startsector == 0)
142 return -3;
144 if (nand_read_sectors(startsector, 1, buffer) != 0)
145 return -4;
147 if (buffer[0x40] != 0x5B68695D)
148 return -5;
150 if (nand_read_sectors(startsector + 1 + (buffer[0x41] >> 11), 1, buffer) != 0)
151 return -6;
153 for (i = 0; i < 0x1FE; i += 10) {
154 if (memcmp(&buffer[i], filename, 8) == 0) {
155 uint32_t filesector = startsector + 1 + (buffer[i + 3] >> 11);
156 *size = buffer[i + 4];
158 if (nand_read_sectors(filesector, ((*size + 0x7FF) >> 11), address) != 0)
159 return -7;
161 /* Success! */
162 return 0;
166 /* Nothing found */
167 return -8;
170 void main(void)
172 int i;
173 int btn;
174 int size;
175 int rc;
176 bool button_was_held;
178 /* Check the button hold status as soon as possible - to
179 give the user maximum chance to turn it on in order to
180 reset the settings in rockbox. */
181 button_was_held = button_hold();
183 system_init();
184 kernel_init();
186 i2c_init();
188 enable_irq();
190 backlight_init(); /* Turns on the backlight */
192 lcd_init();
193 font_init();
195 lcd_set_foreground(LCD_WHITE);
196 lcd_set_background(LCD_BLACK);
197 lcd_clear_display();
199 // button_init();
201 btn=0; /* TODO */
203 /* Enable bootloader messages */
204 if (btn==BUTTON_RIGHT)
205 verbose = true;
207 lcd_setfont(FONT_SYSFIXED);
209 printf("Rockbox boot loader");
210 printf("Version: " RBVERSION);
212 i = storage_init();
214 if (i != 0) {
215 printf("ATA error: %d", i);
216 fatal_error();
219 disk_init();
220 rc = disk_mount_all();
221 if (rc<=0)
223 printf("No partition found");
224 fatal_error();
227 if (button_was_held || (btn==BUTTON_MENU)) {
228 /* If either the hold switch was on, or the Menu button was held, then
229 try the Apple firmware */
230 printf("Loading original firmware...");
232 if ((rc = readfw("DNANkbso", loadbuffer, &size)) < 0) {
233 printf("readfw error %d",rc);
234 fatal_error();
237 /* Now we need to decrypt it */
238 printf("Decrypting %d bytes...",size);
240 aes_decrypt(loadbuffer, size);
241 } else {
242 printf("Loading Rockbox...");
243 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
245 if (rc != EOK) {
246 printf("Error!");
247 printf("Can't load " BOOTFILE ": ");
248 printf(strerror(rc));
249 fatal_error();
252 printf("Rockbox loaded.");
256 /* If we get here, we have a new firmware image at 0x08000000, run it */
257 printf("Executing...");
259 disable_irq();
261 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves
264 MIUCON &= ~1;
266 /* Disable caches and protection unit */
267 asm volatile(
268 "mrc 15, 0, r0, c1, c0, 0 \n"
269 "bic r0, r0, #0x1000 \n"
270 "bic r0, r0, #0x5 \n"
271 "mcr 15, 0, r0, c1, c0, 0 \n"
274 /* Branch to start of DRAM */
275 asm volatile("ldr pc, =0x08000000");