summaryrefslogtreecommitdiff
path: root/bootloader/fiiom3k.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader/fiiom3k.c')
-rw-r--r--bootloader/fiiom3k.c264
1 files changed, 233 insertions, 31 deletions
diff --git a/bootloader/fiiom3k.c b/bootloader/fiiom3k.c
index 9f169755ae..3d42ba7314 100644
--- a/bootloader/fiiom3k.c
+++ b/bootloader/fiiom3k.c
@@ -20,6 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "system.h" 22#include "system.h"
23#include "core_alloc.h"
23#include "kernel/kernel-internal.h" 24#include "kernel/kernel-internal.h"
24#include "i2c.h" 25#include "i2c.h"
25#include "power.h" 26#include "power.h"
@@ -35,6 +36,9 @@
35#include "rb-loader.h" 36#include "rb-loader.h"
36#include "loader_strerror.h" 37#include "loader_strerror.h"
37#include "version.h" 38#include "version.h"
39#include "installer-fiiom3k.h"
40#include "spl-x1000.h"
41#include "x1000/cpm.h"
38 42
39/* Load address where the binary needs to be placed */ 43/* Load address where the binary needs to be placed */
40extern unsigned char loadaddress[]; 44extern unsigned char loadaddress[];
@@ -59,6 +63,7 @@ void exec(void* dst, const void* src, int bytes)
59 63
60static bool lcd_inited = false; 64static bool lcd_inited = false;
61static bool usb_inited = false; 65static bool usb_inited = false;
66static bool disk_inited = false;
62 67
63static void init_lcd(void) 68static void init_lcd(void)
64{ 69{
@@ -79,6 +84,12 @@ static void init_lcd(void)
79 lcd_inited = true; 84 lcd_inited = true;
80} 85}
81 86
87static void put_version(void)
88{
89 lcd_putsxy((LCD_WIDTH - (SYSFONT_WIDTH * strlen(rbversion))) / 2,
90 (LCD_HEIGHT - SYSFONT_HEIGHT), rbversion);
91}
92
82static void do_splash2(int delay, const char* msg, const char* msg2) 93static void do_splash2(int delay, const char* msg, const char* msg2)
83{ 94{
84 init_lcd(); 95 init_lcd();
@@ -90,8 +101,7 @@ static void do_splash2(int delay, const char* msg, const char* msg2)
90 (LCD_HEIGHT + 2*SYSFONT_HEIGHT) / 2, msg2); 101 (LCD_HEIGHT + 2*SYSFONT_HEIGHT) / 2, msg2);
91 } 102 }
92 103
93 lcd_putsxy((LCD_WIDTH - (SYSFONT_WIDTH * strlen(rbversion))) / 2, 104 put_version();
94 (LCD_HEIGHT - SYSFONT_HEIGHT), rbversion);
95 lcd_update(); 105 lcd_update();
96 sleep(delay); 106 sleep(delay);
97} 107}
@@ -109,20 +119,232 @@ static void do_usb(void)
109 usb_inited = true; 119 usb_inited = true;
110 } 120 }
111 121
112 do_splash(0, "Waiting for USB"); 122 do_splash2(0, "Waiting for USB", "Press POWER to go back");
113 123
114 while(button_get(true) != SYS_USB_CONNECTED); 124 int btn;
115 do_splash(0, "USB mode"); 125 while(1) {
126 btn = button_get(true);
127 if(btn == SYS_USB_CONNECTED)
128 break;
129 else if(btn == BUTTON_POWER)
130 return;
131 }
116 132
133 do_splash(0, "USB mode");
117 usb_acknowledge(SYS_USB_CONNECTED_ACK); 134 usb_acknowledge(SYS_USB_CONNECTED_ACK);
118 while(button_get(true) != SYS_USB_DISCONNECTED); 135 while(button_get(true) != SYS_USB_DISCONNECTED);
119 136
120 do_splash(3*HZ, "USB disconnected"); 137 do_splash(3*HZ, "USB disconnected");
121} 138}
122 139
140static int init_disk(void)
141{
142 if(disk_inited)
143 return 0;
144
145 while(!storage_present(0)) {
146 do_splash2(0, "Insert SD card", "Press POWER for recovery");
147 int btn = button_get_w_tmo(HZ);
148 if(btn == BUTTON_POWER)
149 return 1;
150 }
151
152 if(disk_mount_all() <= 0) {
153 do_splash(5*HZ, "Cannot mount filesystem");
154 return 1;
155 }
156
157 disk_inited = true;
158 return 0;
159}
160
161static void do_boot(void)
162{
163 if(init_disk() != 0)
164 return;
165
166 int loadsize = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE);
167 if(loadsize <= 0) {
168 do_splash2(5*HZ, "Error loading Rockbox",
169 loader_strerror(loadsize));
170 do_usb();
171 return;
172 }
173
174 if(lcd_inited)
175 backlight_hw_off();
176
177 disable_irq();
178 exec(loadaddress, loadbuffer, loadsize);
179}
180
181#define INSTALL 0
182#define BACKUP 1
183#define RESTORE 2
184
185static void do_install(int which)
186{
187 int rc = init_disk();
188 if(rc != 0) {
189 do_splash2(5*HZ, "Install aborted", "No SD card present");
190 return;
191 }
192
193 const char* msg;
194 if(rc == INSTALL)
195 msg = "Installing";
196 else if(rc == BACKUP)
197 msg = "Backing up";
198 else
199 msg = "Restoring backup";
200
201 do_splash(0, msg);
202
203 if(which == INSTALL)
204 rc = install_boot("/bootloader.m3k");
205 else if(which == BACKUP)
206 rc = backup_boot("/fiiom3k-boot.bin");
207 else
208 rc = restore_boot("/fiiom3k-boot.bin");
209
210 char buf[32];
211 snprintf(buf, sizeof(buf), "Failed! Error: %d", rc);
212 const char* msg1 = rc == 0 ? "Success" : buf;
213 const char* msg2 = "Press POWER to continue";
214 do_splash2(0, msg1, msg2);
215
216 button_clear_queue();
217 while(button_get(true) != BUTTON_POWER);
218}
219
220static void recovery_menu(void)
221{
222 static const char* items[] = {
223 "--- Rockbox recovery menu ---",
224 "[System]",
225 " Start Rockbox",
226 " USB mode",
227 " Shutdown",
228 " Reboot",
229 "[Bootloader]",
230 " Install or update",
231 " Backup",
232 " Restore",
233 "",
234 "",
235 "",
236 "",
237 "",
238 "VOL+/VOL- move cursor",
239 "PLAY select item",
240 "POWER power off",
241 };
242
243 static const int nitems = sizeof(items) / sizeof(char*);
244
245 init_lcd();
246
247 int selection = 2;
248 do {
249 /* Draw menu */
250 lcd_clear_display();
251
252 for(int i = 0; i < nitems; ++i)
253 lcd_puts(0, i, items[i]);
254
255 if(items[selection][0] == ' ')
256 lcd_puts(0, selection, "=>");
257
258 put_version();
259 lcd_update();
260
261 /* Clear queue to avoid accidental input */
262 button_clear_queue();
263
264 /* Get the button */
265 int btn = button_get(true);
266
267 /* Process user input */
268 if(btn == BUTTON_VOL_UP) {
269 for(int i = selection-1; i >= 0; --i) {
270 if(items[i][0] == ' ') {
271 selection = i;
272 break;
273 }
274 }
275
276 continue;
277 } else if(btn == BUTTON_VOL_DOWN) {
278 for(int i = selection+1; i < nitems; ++i) {
279 if(items[i][0] == ' ') {
280 selection = i;
281 break;
282 }
283 }
284
285 continue;
286 } else if(btn == BUTTON_POWER) {
287 selection = 4; /* Shutdown */
288 } else if(btn != BUTTON_PLAY) {
289 continue;
290 }
291
292 /* User pressed PLAY so decide what action to take */
293 switch(selection) {
294 case 2: /* Start rockbox */
295 do_boot();
296 break;
297
298 case 3: /* USB mode */
299 do_usb();
300 break;
301
302 case 4: /* Shutdown */
303 do_splash(HZ, "Shutting down");
304 power_off();
305 break;
306
307 case 5: /* Reboot */
308 do_splash(HZ, "Rebooting");
309 system_reboot();
310 break;
311
312 case 7: /* Install bootloader */
313 do_install(INSTALL);
314 break;
315
316 case 8: /* Backup bootloader */
317 do_install(BACKUP);
318 break;
319
320 case 9: /* Restore bootloader */
321 do_install(RESTORE);
322 break;
323
324 default:
325 break;
326 }
327 } while(1);
328}
329
123void main(void) 330void main(void)
124{ 331{
332 bool recovery_mode = false;
333
334 /* This hack is needed because when USB booting, we cannot initialize
335 * clocks in the SPL -- it may break the mask ROM's USB code. So if the
336 * SPL has not already initialized the clocks, we need to do that now.
337 *
338 * Also use this as a sign that we should enter the recovery menu since
339 * this is probably the expected result if the user is USB booting...
340 */
341 if(jz_readf(CPM_MPCR, ENABLE)) {
342 spl_handle_pre_boot(0);
343 recovery_mode = true;
344 }
345
125 system_init(); 346 system_init();
347 core_allocator_init();
126 kernel_init(); 348 kernel_init();
127 i2c_init(); 349 i2c_init();
128 power_init(); 350 power_init();
@@ -136,32 +358,12 @@ void main(void)
136 358
137 filesystem_init(); 359 filesystem_init();
138 360
139 int loadsize = 0; 361 if(button_read_device() & BUTTON_VOL_UP)
140 do { 362 recovery_mode = true;
141 if(!storage_present(0)) {
142 do_splash(HZ, "Insert SD card");
143 continue;
144 }
145
146 if(disk_mount_all() <= 0) {
147 do_splash(5*HZ, "Cannot mount filesystem");
148 do_usb();
149 continue;
150 }
151
152 loadsize = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE);
153 if(loadsize <= 0) {
154 do_splash2(5*HZ, "Error loading Rockbox",
155 loader_strerror(loadsize));
156 do_usb();
157 continue;
158 }
159 } while(loadsize <= 0);
160 363
161 if(lcd_inited) 364 if(!recovery_mode)
162 backlight_hw_off(); 365 do_boot();
163 366
164 disable_irq(); 367 /* If boot fails or user holds Vol+, go to recovery menu */
165 368 recovery_menu();
166 exec(loadaddress, loadbuffer, loadsize);
167} 369}