change the %St tag so it only shows the filename of file settings, not the full path...
[kugel-rb.git] / bootloader / ipodnano2g.c
blob020da207bddc96441322c5e261de12bf41f5a9f9
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"
48 /* Safety measure - maximum allowed firmware image size.
49 The largest known current (October 2009) firmware is about 6.2MB so
50 we set this to 8MB.
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;
60 extern int line;
62 void fatal_error(void)
64 extern int line;
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");
71 lcd_update();
73 while (1) {
74 if (button_hold() != holdstatus) {
75 if (button_hold()) {
76 holdstatus=true;
77 lcd_puts(0, line, "Hold switch on!");
78 } else {
79 holdstatus=false;
80 lcd_puts(0, line, " ");
82 lcd_update();
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)
93 uint32_t ptr, i;
94 uint32_t go = 1;
96 PWRCONEXT &= ~0x400;
97 AESTYPE = 1;
98 AESUNKREG0 = 1;
99 AESUNKREG0 = 0;
100 AESCONTROL = 1;
101 AESKEYLEN = 8;
102 AESOUTSIZE = size;
103 AESAUXSIZE = 0x10;
104 AESINSIZE = 0x10;
105 AESSIZE3 = 0x10;
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);
111 AESSTATUS = 6;
112 AESGO = go;
113 go = 3;
114 while ((AESSTATUS & 6) == 0);
115 if (ptr == 0) break;
116 for (i = 0; i < 4; i++)
117 ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
119 AESCONTROL = 0;
120 PWRCONEXT |= 0x400;
123 static int readfw(char* filename, void* address, int* size)
125 int i;
126 uint32_t startsector = 0;
127 uint32_t buffer[0x200];
129 if (nand_read_sectors(0, 1, buffer) != 0)
130 return -1;
132 if (*((uint16_t*)((uint32_t)buffer + 0x1FE)) != 0xAA55)
133 return -2;
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);
139 break;
143 if (startsector == 0)
144 return -3;
146 if (nand_read_sectors(startsector, 1, buffer) != 0)
147 return -4;
149 if (buffer[0x40] != 0x5B68695D)
150 return -5;
152 if (nand_read_sectors(startsector + 1 + (buffer[0x41] >> 11), 1, buffer) != 0)
153 return -6;
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)
161 return -7;
163 /* Success! */
164 return 0;
168 /* Nothing found */
169 return -8;
172 void main(void)
174 int i;
175 int btn;
176 int size;
177 int rc;
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();
185 system_init();
186 kernel_init();
188 i2c_init();
190 enable_irq();
192 backlight_init(); /* Turns on the backlight */
194 lcd_init();
195 font_init();
197 lcd_set_foreground(LCD_WHITE);
198 lcd_set_background(LCD_BLACK);
199 lcd_clear_display();
201 // button_init();
203 btn=0; /* TODO */
205 /* Enable bootloader messages */
206 if (btn==BUTTON_RIGHT)
207 verbose = true;
209 lcd_setfont(FONT_SYSFIXED);
211 printf("Rockbox boot loader");
212 printf("Version: %s", version);
214 i = storage_init();
216 if (i != 0) {
217 printf("ATA error: %d", i);
218 fatal_error();
221 disk_init();
222 rc = disk_mount_all();
223 if (rc<=0)
225 printf("No partition found");
226 fatal_error();
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);
236 fatal_error();
239 /* Now we need to decrypt it */
240 printf("Decrypting %d bytes...",size);
242 aes_decrypt(loadbuffer, size);
243 } else {
244 printf("Loading Rockbox...");
245 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE);
247 if (rc != EOK) {
248 printf("Error!");
249 printf("Can't load " BOOTFILE ": ");
250 printf(strerror(rc));
251 fatal_error();
254 printf("Rockbox loaded.");
258 /* If we get here, we have a new firmware image at 0x08000000, run it */
259 printf("Executing...");
261 disable_irq();
263 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves
266 MIUCON &= ~1;
268 /* Disable caches and protection unit */
269 asm volatile(
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");