Oops, correct typo that made the previous commit useless
[kugel-rb.git] / bootloader / ondavx747.c
blob20f47d5224c43fd0c196cea074edd56f025a7bca
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"
37 extern int show_logo(void);
38 extern void power_off(void);
40 static void show_splash(int timeout, const char *msg)
42 reset_screen();
43 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
44 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
45 lcd_update();
47 sleep(timeout);
50 static void usb_mode(void)
52 int button;
54 /* Init USB */
55 usb_init();
56 usb_start_monitoring();
58 /* Wait for threads to connect */
59 show_splash(HZ/2, "Waiting for USB");
61 while (1)
63 button = button_get_w_tmo(HZ/2);
65 if (button == SYS_USB_CONNECTED)
66 break; /* Hit */
69 if (button == SYS_USB_CONNECTED)
71 /* Got the message - wait for disconnect */
72 show_splash(0, "Bootloader USB mode");
74 usb_acknowledge(SYS_USB_CONNECTED_ACK);
76 while (1)
78 button = button_get(true);
79 if (button == SYS_USB_DISCONNECTED)
81 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
82 break;
88 static int boot_of(void)
90 int fd, rc, len, i, checksum = 0;
91 void (*kernel_entry)(int, void*, void*);
93 printf("Mounting disk...");
94 rc = disk_mount_all();
95 if (rc <= 0)
96 error(EDISK,rc);
98 /* TODO: get this from the NAND flash instead of SD */
99 fd = open("/ccpmp.bin", O_RDONLY);
100 if(fd < 0)
101 return EFILE_NOT_FOUND;
103 lseek(fd, 4, SEEK_SET);
104 rc = read(fd, (char*)&len, 4); /* CPU is LE */
105 if(rc < 4)
106 return EREAD_IMAGE_FAILED;
108 len += 8;
109 printf("Reading %d bytes...", len);
111 lseek(fd, 0, SEEK_SET);
112 rc = read(fd, (void*)0x80004000, len);
113 if(rc < len)
114 return EREAD_IMAGE_FAILED;
116 close(fd);
118 for(i=0; i<len; i++)
119 checksum += ((unsigned char*)0x80004000)[i];
121 *((unsigned int*)0x80004000) = checksum;
123 printf("Starting the OF...");
125 /* OF requires all clocks on */
126 __cpm_start_all();
128 disable_interrupt();
129 __dcache_writeback_all();
130 __icache_invalidate_all();
132 for(i=8000; i>0; i--)
133 asm volatile("nop\n");
135 kernel_entry = (void*) 0x80004008;
136 kernel_entry(0, "Jan 10 2008", "15:34:42"); /* Reversed from the SPL */
138 return 0; /* Shouldn't happen */
141 static int boot_rockbox(void)
143 int rc;
144 void (*kernel_entry)(void);
146 printf("Mounting disk...");
147 rc = disk_mount_all();
148 if (rc <= 0)
149 error(EDISK,rc);
151 printf("Loading firmware...");
152 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
153 if(rc < 0)
154 return rc;
155 else
157 printf("Starting Rockbox...");
158 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */
160 disable_interrupt();
161 kernel_entry = (void*) CONFIG_SDRAM_START;
162 kernel_entry();
164 return 0; /* Shouldn't happen */
168 static void reset_configuration(void)
170 int rc;
172 rc = disk_mount_all();
173 if (rc <= 0)
174 error(EDISK,rc);
176 if(rename(ROCKBOX_DIR "/config.cfg", ROCKBOX_DIR "/config.old") == 0)
177 show_splash(HZ/2, "Configuration reset successfully!");
178 else
179 show_splash(HZ/2, "Couldn't reset configuration!");
182 #define RECT_X (LCD_WIDTH/8)
183 #define RECT_Y(i) (LCD_HEIGHT/20 + LCD_HEIGHT/10*i + RECT_HEIGHT*i)
184 #define RECT_WIDTH (LCD_WIDTH*3/4)
185 #define RECT_HEIGHT (LCD_HEIGHT/ARRAYLEN(strings) - LCD_HEIGHT/10)
186 #define TEXT_X(i) (RECT_X + RECT_WIDTH/2 - strlen(strings[i])*SYSFONT_WIDTH/2)
187 #define TEXT_Y(i) (RECT_Y(i) + RECT_HEIGHT/2 - SYSFONT_HEIGHT/2)
188 static int boot_menu(void)
190 const char* strings[] = {"Boot Rockbox", "Boot OF", "USB mode", "Reset Rockbox configuration"};
191 int button, touch, poweroff_repeat = 0;
192 unsigned int i;
194 verbose = true;
195 adc_init();
197 redraw:
198 lcd_clear_display();
199 for(i=0; i<ARRAYLEN(strings); i++)
201 lcd_drawrect(RECT_X, RECT_Y(i), RECT_WIDTH, RECT_HEIGHT);
202 lcd_putsxy(TEXT_X(i), TEXT_Y(i), strings[i]);
204 lcd_update();
206 while(1)
208 button = button_get_w_tmo(HZ/4);
209 if(button & BUTTON_TOUCHSCREEN)
211 touch = button_get_data();
212 unsigned int x = touch & 0xFFFF, y = touch >> 16;
213 int found = -1;
214 for(i=0; i<ARRAYLEN(strings); i++)
216 if(x > RECT_X && x < RECT_X+RECT_WIDTH &&
217 y > RECT_Y(i) && y < RECT_Y(i)+RECT_HEIGHT)
219 found = i;
220 break;
224 switch(found)
226 case 0:
227 reset_screen();
228 boot_rockbox();
229 break;
230 case 1:
231 reset_screen();
232 boot_of();
233 break;
234 case 2:
235 usb_mode();
236 break;
237 case 3:
238 reset_configuration();
239 break;
242 if(found != -1)
243 goto redraw;
245 else if(button & BUTTON_POWER)
247 if(poweroff_repeat++ > 8)
248 power_off();
250 else
251 poweroff_repeat = 0;
255 int main(void)
257 int rc;
258 #ifdef HAVE_TOUCHSCREEN
259 int dummy;
260 #endif
262 kernel_init();
263 lcd_init();
264 font_init();
265 lcd_setfont(FONT_SYSFIXED);
266 button_init();
267 backlight_init();
269 show_logo();
271 rc = storage_init();
272 if(rc)
273 error(EATA, rc);
275 /* Don't mount the disks yet, there could be file system/partition errors
276 which are fixable in USB mode */
278 #ifdef HAVE_TOUCHSCREEN
279 rc = button_read_device(&dummy);
280 #else
281 rc = button_read_device();
282 #endif
284 if(rc)
285 verbose = true;
287 #ifdef BUTTON_VOL_UP
288 if(rc & BUTTON_VOL_UP ||
289 #endif
290 #ifdef BUTTON_POWER
291 rc & BUTTON_POWER ||
292 #endif
294 rc = boot_menu();
296 if(verbose)
297 reset_screen();
298 printf(MODEL_NAME" Rockbox Bootloader");
299 printf("Version "APPSVERSION);
301 #ifdef HAS_BUTTON_HOLD
302 if(button_hold())
303 rc = boot_of();
304 else
305 #endif
306 rc = boot_rockbox();
308 if(rc < 0)
309 printf("Error: %s", strerror(rc));
311 /* Halt */
312 while (1)
313 core_idle();
315 return 0;