Merge branch 'master' into app-list-itemsize
[kugel-rb.git] / bootloader / ondavx747.c
blob42a6075bfc7fafbb0a06744122bf21e94e3a38dd
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Maurus Cuelenaere
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 "config.h"
23 #include "jz4740.h"
24 #include "backlight.h"
25 #include "font.h"
26 #include "lcd.h"
27 #include "file.h"
28 #include "usb.h"
29 #include "system.h"
30 #include "button.h"
31 #include "common.h"
32 #include "storage.h"
33 #include "disk.h"
34 #include "string.h"
35 #include "adc.h"
36 #include "version.h"
38 extern int show_logo(void);
39 extern void power_off(void);
41 static void show_splash(int timeout, const char *msg)
43 reset_screen();
44 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
45 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
46 lcd_update();
48 sleep(timeout);
51 static void usb_mode(void)
53 int button;
55 /* Init USB */
56 usb_init();
57 usb_start_monitoring();
59 /* Wait for threads to connect */
60 show_splash(HZ/2, "Waiting for USB");
62 while (1)
64 button = button_get_w_tmo(HZ/2);
66 if (button == SYS_USB_CONNECTED)
67 break; /* Hit */
70 if (button == SYS_USB_CONNECTED)
72 /* Got the message - wait for disconnect */
73 show_splash(0, "Bootloader USB mode");
75 usb_acknowledge(SYS_USB_CONNECTED_ACK);
77 while (1)
79 button = button_get(true);
80 if (button == SYS_USB_DISCONNECTED)
81 break;
86 static int boot_of(void)
88 int fd, rc, len, i, checksum = 0;
89 void (*kernel_entry)(int, void*, void*);
91 printf("Mounting disk...");
92 rc = disk_mount_all();
93 if (rc <= 0)
94 error(EDISK, rc, true);
96 /* TODO: get this from the NAND flash instead of SD */
97 fd = open("/ccpmp.bin", O_RDONLY);
98 if(fd < 0)
99 return EFILE_NOT_FOUND;
101 lseek(fd, 4, SEEK_SET);
102 rc = read(fd, (char*)&len, 4); /* CPU is LE */
103 if(rc < 4)
104 return EREAD_IMAGE_FAILED;
106 len += 8;
107 printf("Reading %d bytes...", len);
109 lseek(fd, 0, SEEK_SET);
110 rc = read(fd, (void*)0x80004000, len);
111 if(rc < len)
112 return EREAD_IMAGE_FAILED;
114 close(fd);
116 for(i=0; i<len; i++)
117 checksum += ((unsigned char*)0x80004000)[i];
119 *((unsigned int*)0x80004000) = checksum;
121 printf("Starting the OF...");
123 /* OF requires all clocks on */
124 __cpm_start_all();
126 disable_interrupt();
127 __dcache_writeback_all();
128 __icache_invalidate_all();
130 for(i=8000; i>0; i--)
131 asm volatile("nop\n");
133 kernel_entry = (void*) 0x80004008;
134 kernel_entry(0, "Jan 10 2008", "15:34:42"); /* Reversed from the SPL */
136 return 0; /* Shouldn't happen */
139 static int boot_rockbox(void)
141 int rc;
142 void (*kernel_entry)(void);
144 printf("Mounting disk...");
145 rc = disk_mount_all();
146 if (rc <= 0)
147 error(EDISK,rc, true);
149 printf("Loading firmware...");
150 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
151 if(rc < 0)
152 return rc;
153 else
155 printf("Starting Rockbox...");
156 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */
158 disable_interrupt();
159 kernel_entry = (void*) CONFIG_SDRAM_START;
160 kernel_entry();
162 return 0; /* Shouldn't happen */
166 static void reset_configuration(void)
168 int rc;
170 rc = disk_mount_all();
171 if (rc <= 0)
172 error(EDISK,rc, true);
174 if(rename(ROCKBOX_DIR "/config.cfg", ROCKBOX_DIR "/config.old") == 0)
175 show_splash(HZ/2, "Configuration reset successfully!");
176 else
177 show_splash(HZ/2, "Couldn't reset configuration!");
180 #define RECT_X (LCD_WIDTH/8)
181 #define RECT_Y(i) (LCD_HEIGHT/20 + LCD_HEIGHT/10*i + RECT_HEIGHT*i)
182 #define RECT_WIDTH (LCD_WIDTH*3/4)
183 #define RECT_HEIGHT (LCD_HEIGHT/ARRAYLEN(strings) - LCD_HEIGHT/10)
184 #define TEXT_X(i) (RECT_X + RECT_WIDTH/2 - strlen(strings[i])*SYSFONT_WIDTH/2)
185 #define TEXT_Y(i) (RECT_Y(i) + RECT_HEIGHT/2 - SYSFONT_HEIGHT/2)
186 static int boot_menu(void)
188 const char* strings[] = {"Boot Rockbox", "Boot OF", "USB mode", "Reset Rockbox configuration"};
189 int button, touch, poweroff_repeat = 0;
190 unsigned int i;
192 verbose = true;
193 adc_init();
195 redraw:
196 lcd_clear_display();
197 for(i=0; i<ARRAYLEN(strings); i++)
199 lcd_drawrect(RECT_X, RECT_Y(i), RECT_WIDTH, RECT_HEIGHT);
200 lcd_putsxy(TEXT_X(i), TEXT_Y(i), strings[i]);
202 lcd_update();
204 while(1)
206 button = button_get_w_tmo(HZ/4);
207 if(button & BUTTON_TOUCHSCREEN)
209 touch = button_get_data();
210 unsigned int x = touch & 0xFFFF, y = touch >> 16;
211 int found = -1;
212 for(i=0; i<ARRAYLEN(strings); i++)
214 if(x > RECT_X && x < RECT_X+RECT_WIDTH &&
215 y > RECT_Y(i) && y < RECT_Y(i)+RECT_HEIGHT)
217 found = i;
218 break;
222 switch(found)
224 case 0:
225 reset_screen();
226 boot_rockbox();
227 break;
228 case 1:
229 reset_screen();
230 boot_of();
231 break;
232 case 2:
233 usb_mode();
234 break;
235 case 3:
236 reset_configuration();
237 break;
240 if(found != -1)
241 goto redraw;
243 else if(button & BUTTON_POWER)
245 if(poweroff_repeat++ > 8)
246 power_off();
248 else
249 poweroff_repeat = 0;
253 int main(void)
255 int rc;
256 #ifdef HAVE_TOUCHSCREEN
257 int dummy;
258 #endif
260 kernel_init();
261 lcd_init();
262 font_init();
263 lcd_setfont(FONT_SYSFIXED);
264 button_init();
265 backlight_init();
267 show_logo();
269 rc = storage_init();
270 if(rc)
271 error(EATA, rc, true);
273 /* Don't mount the disks yet, there could be file system/partition errors
274 which are fixable in USB mode */
276 #ifdef HAVE_TOUCHSCREEN
277 rc = button_read_device(&dummy);
278 #else
279 rc = button_read_device();
280 #endif
282 if(rc)
283 verbose = true;
285 #ifdef BUTTON_VOL_UP
286 if(rc & BUTTON_VOL_UP ||
287 #endif
288 #ifdef BUTTON_POWER
289 rc & BUTTON_POWER ||
290 #endif
292 rc = boot_menu();
294 if(verbose)
295 reset_screen();
296 printf(MODEL_NAME" Rockbox Bootloader");
297 printf("Version " RBVERSION);
299 #ifdef HAS_BUTTON_HOLD
300 if(button_hold())
301 rc = boot_of();
302 else
303 #endif
304 rc = boot_rockbox();
306 if(rc < 0)
307 printf("Error: %s", strerror(rc));
309 /* Halt */
310 while (1)
311 core_idle();
313 return 0;