blob: cdacb69bd2f06379f055b91c1a85cf4255aceb60 [file] [log] [blame]
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +000022#include "config.h"
23#include "jz4740.h"
Michael Sevakis4ea4cdf2014-08-08 02:28:11 -040024#include "../kernel-internal.h"
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +000025#include "backlight.h"
26#include "font.h"
27#include "lcd.h"
Nils Wallménius304c6222009-08-19 22:36:39 +000028#include "file.h"
Maurus Cuelenaere40ec5432008-12-19 11:13:58 +000029#include "usb.h"
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +000030#include "system.h"
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +000031#include "button.h"
Maurus Cuelenaere975261f2008-07-16 15:25:35 +000032#include "common.h"
Marcin Bukat0b296912012-03-04 15:34:29 +010033#include "rb-loader.h"
34#include "loader_strerror.h"
Maurus Cuelenaere9da24562008-12-19 11:29:18 +000035#include "storage.h"
Michael Sevakis7d1a47c2013-08-05 22:02:45 -040036#include "file_internal.h"
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000037#include "disk.h"
38#include "string.h"
Maurus Cuelenaerebe8a27a2009-04-20 18:28:51 +000039#include "adc.h"
Rafaël Carré5d236b22010-05-27 09:41:46 +000040#include "version.h"
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +000041
Bertrik Sikken7e3a3f42011-09-08 18:31:15 +000042extern void show_logo(void);
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +000043extern void power_off(void);
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +000044
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000045static void show_splash(int timeout, const char *msg)
46{
47 reset_screen();
48 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
49 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
50 lcd_update();
51
52 sleep(timeout);
53}
54
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000055static void usb_mode(void)
56{
57 int button;
Maurus Cuelenaerec4682732009-07-01 14:39:39 +000058
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000059 /* Init USB */
60 usb_init();
61 usb_start_monitoring();
62
63 /* Wait for threads to connect */
64 show_splash(HZ/2, "Waiting for USB");
65
66 while (1)
67 {
68 button = button_get_w_tmo(HZ/2);
69
70 if (button == SYS_USB_CONNECTED)
71 break; /* Hit */
72 }
73
74 if (button == SYS_USB_CONNECTED)
75 {
76 /* Got the message - wait for disconnect */
77 show_splash(0, "Bootloader USB mode");
78
79 usb_acknowledge(SYS_USB_CONNECTED_ACK);
80
81 while (1)
82 {
83 button = button_get(true);
84 if (button == SYS_USB_DISCONNECTED)
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000085 break;
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000086 }
87 }
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000088}
89
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +000090static int boot_of(void)
Maurus Cuelenaere04c73792009-02-09 10:02:38 +000091{
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +000092 int fd, rc, len, i, checksum = 0;
93 void (*kernel_entry)(int, void*, void*);
94
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +000095 printf("Mounting disk...");
96 rc = disk_mount_all();
97 if (rc <= 0)
Rafaël Carré1ec82122010-06-23 05:08:36 +000098 error(EDISK, rc, true);
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +000099
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000100 /* TODO: get this from the NAND flash instead of SD */
101 fd = open("/ccpmp.bin", O_RDONLY);
102 if(fd < 0)
103 return EFILE_NOT_FOUND;
104
105 lseek(fd, 4, SEEK_SET);
106 rc = read(fd, (char*)&len, 4); /* CPU is LE */
107 if(rc < 4)
108 return EREAD_IMAGE_FAILED;
109
110 len += 8;
111 printf("Reading %d bytes...", len);
112
113 lseek(fd, 0, SEEK_SET);
114 rc = read(fd, (void*)0x80004000, len);
115 if(rc < len)
116 return EREAD_IMAGE_FAILED;
117
118 close(fd);
119
120 for(i=0; i<len; i++)
121 checksum += ((unsigned char*)0x80004000)[i];
122
123 *((unsigned int*)0x80004000) = checksum;
124
125 printf("Starting the OF...");
126
127 /* OF requires all clocks on */
128 __cpm_start_all();
129
130 disable_interrupt();
131 __dcache_writeback_all();
132 __icache_invalidate_all();
133
134 for(i=8000; i>0; i--)
135 asm volatile("nop\n");
136
137 kernel_entry = (void*) 0x80004008;
138 kernel_entry(0, "Jan 10 2008", "15:34:42"); /* Reversed from the SPL */
139
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000140 return 0; /* Shouldn't happen */
141}
142
143static int boot_rockbox(void)
144{
145 int rc;
146 void (*kernel_entry)(void);
147
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000148 printf("Mounting disk...");
149 rc = disk_mount_all();
150 if (rc <= 0)
Rafaël Carré1ec82122010-06-23 05:08:36 +0000151 error(EDISK,rc, true);
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000152
153 printf("Loading firmware...");
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000154 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000);
Marcin Bukat0b296912012-03-04 15:34:29 +0100155 if(rc <= EFILE_EMPTY)
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000156 return rc;
157 else
158 {
159 printf("Starting Rockbox...");
160 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */
161
162 disable_interrupt();
163 kernel_entry = (void*) CONFIG_SDRAM_START;
164 kernel_entry();
165
166 return 0; /* Shouldn't happen */
167 }
168}
169
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000170static void reset_configuration(void)
171{
172 int rc;
173
174 rc = disk_mount_all();
175 if (rc <= 0)
Rafaël Carré1ec82122010-06-23 05:08:36 +0000176 error(EDISK,rc, true);
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000177
178 if(rename(ROCKBOX_DIR "/config.cfg", ROCKBOX_DIR "/config.old") == 0)
179 show_splash(HZ/2, "Configuration reset successfully!");
180 else
181 show_splash(HZ/2, "Couldn't reset configuration!");
182}
183
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000184#define RECT_X (LCD_WIDTH/8)
185#define RECT_Y(i) (LCD_HEIGHT/20 + LCD_HEIGHT/10*i + RECT_HEIGHT*i)
186#define RECT_WIDTH (LCD_WIDTH*3/4)
187#define RECT_HEIGHT (LCD_HEIGHT/ARRAYLEN(strings) - LCD_HEIGHT/10)
188#define TEXT_X(i) (RECT_X + RECT_WIDTH/2 - strlen(strings[i])*SYSFONT_WIDTH/2)
189#define TEXT_Y(i) (RECT_Y(i) + RECT_HEIGHT/2 - SYSFONT_HEIGHT/2)
190static int boot_menu(void)
191{
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000192 const char* strings[] = {"Boot Rockbox", "Boot OF", "USB mode", "Reset Rockbox configuration"};
Maurus Cuelenaerebfd42d62009-09-01 07:57:56 +0000193 int button, touch, poweroff_repeat = 0;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000194 unsigned int i;
195
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000196 verbose = true;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000197 adc_init();
198
199redraw:
200 lcd_clear_display();
201 for(i=0; i<ARRAYLEN(strings); i++)
202 {
203 lcd_drawrect(RECT_X, RECT_Y(i), RECT_WIDTH, RECT_HEIGHT);
204 lcd_putsxy(TEXT_X(i), TEXT_Y(i), strings[i]);
205 }
206 lcd_update();
207
208 while(1)
209 {
210 button = button_get_w_tmo(HZ/4);
Maurus Cuelenaerebfd42d62009-09-01 07:57:56 +0000211 if(button & BUTTON_TOUCHSCREEN)
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000212 {
213 touch = button_get_data();
214 unsigned int x = touch & 0xFFFF, y = touch >> 16;
215 int found = -1;
216 for(i=0; i<ARRAYLEN(strings); i++)
217 {
218 if(x > RECT_X && x < RECT_X+RECT_WIDTH &&
219 y > RECT_Y(i) && y < RECT_Y(i)+RECT_HEIGHT)
220 {
221 found = i;
222 break;
223 }
224 }
225
226 switch(found)
227 {
228 case 0:
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000229 reset_screen();
230 boot_rockbox();
231 break;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000232 case 1:
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000233 reset_screen();
234 boot_of();
235 break;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000236 case 2:
237 usb_mode();
238 break;
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000239 case 3:
240 reset_configuration();
241 break;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000242 }
243
244 if(found != -1)
245 goto redraw;
246 }
Maurus Cuelenaerebfd42d62009-09-01 07:57:56 +0000247 else if(button & BUTTON_POWER)
Andree Buschmann5cebdcd2010-01-03 11:12:31 +0000248 {
249 if(poweroff_repeat++ > 8)
250 power_off();
251 }
252 else
253 poweroff_repeat = 0;
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000254 }
Solomon Peachye6b23a82018-10-15 14:25:48 -0400255 return 0;
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000256}
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +0000257
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +0000258int main(void)
Maurus Cuelenaere4bf4d2b2008-08-10 21:44:48 +0000259{
Maurus Cuelenaere3369a742009-04-21 15:47:39 +0000260 int rc;
261#ifdef HAVE_TOUCHSCREEN
262 int dummy;
263#endif
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000264
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +0000265 kernel_init();
266 lcd_init();
267 font_init();
268 lcd_setfont(FONT_SYSFIXED);
269 button_init();
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000270 backlight_init();
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +0000271
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000272 show_logo();
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000273
Michael Sevakis7d1a47c2013-08-05 22:02:45 -0400274 filesystem_init();
275
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000276 rc = storage_init();
277 if(rc)
Rafaël Carré1ec82122010-06-23 05:08:36 +0000278 error(EATA, rc, true);
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000279
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000280 /* Don't mount the disks yet, there could be file system/partition errors
281 which are fixable in USB mode */
282
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000283#ifdef HAVE_TOUCHSCREEN
Maurus Cuelenaere4532d142009-02-13 00:45:49 +0000284 rc = button_read_device(&dummy);
Maurus Cuelenaere9407ae82008-09-17 21:44:47 +0000285#else
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000286 rc = button_read_device();
Maurus Cuelenaeree1446382008-09-05 15:09:40 +0000287#endif
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000288
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000289 if(rc)
290 verbose = true;
291
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000292#ifdef BUTTON_VOL_UP
293 if(rc & BUTTON_VOL_UP ||
294#endif
Maurus Cuelenaeref7b4ed32009-08-21 22:37:27 +0000295#ifdef BUTTON_POWER
296 rc & BUTTON_POWER ||
297#endif
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000298 0)
299 rc = boot_menu();
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000300
301 if(verbose)
302 reset_screen();
303 printf(MODEL_NAME" Rockbox Bootloader");
Michael Sevakis95a4c3a2014-08-28 10:26:45 -0400304 printf("Version %s", rbversion);
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000305
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000306#ifdef HAS_BUTTON_HOLD
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000307 if(button_hold())
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000308 rc = boot_of();
Maurus Cuelenaerecaf20112009-08-19 00:26:06 +0000309 else
310#endif
311 rc = boot_rockbox();
Maurus Cuelenaerecf9935d2009-07-17 14:30:42 +0000312
Marcin Bukat0b296912012-03-04 15:34:29 +0100313 if(rc <= EFILE_EMPTY)
314 printf("Error: %s", loader_strerror(rc));
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000315
Maurus Cuelenaere04c73792009-02-09 10:02:38 +0000316 /* Halt */
317 while (1)
318 core_idle();
Maurus Cuelenaerec4682732009-07-01 14:39:39 +0000319
Maurus Cuelenaere0709f0a2008-07-14 15:03:10 +0000320 return 0;
321}