blob: 8fd95d048c95477bba410d2dfae67fd4edebb0c3 [file] [log] [blame]
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22
23#include <stdlib.h>
24#include <stdio.h>
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +000025#include "inttypes.h"
26#include "string.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000027#include "cpu.h"
28#include "system.h"
29#include "lcd.h"
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000030#include "lcd-remote.h"
Michael Sevakis5832b592007-07-28 08:45:57 +000031#include "scroll_engine.h"
Michael Sevakis4ea4cdf2014-08-08 02:28:11 -040032#include "../kernel-internal.h"
Frank Gevaerts2f8a0082008-11-01 16:14:28 +000033#include "storage.h"
Michael Sevakis7d1a47c2013-08-05 22:02:45 -040034#include "file_internal.h"
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +000035#include "usb.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000036#include "disk.h"
37#include "font.h"
38#include "adc.h"
39#include "backlight.h"
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000040#include "backlight-target.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000041#include "button.h"
42#include "panic.h"
43#include "power.h"
Jens Arnold0b7391e2007-08-17 07:06:54 +000044#include "powermgmt.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000045#include "file.h"
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +000046#include "eeprom_settings.h"
Linus Nielsen Feltzing48556152007-03-02 13:58:00 +000047#include "rbunicode.h"
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000048#include "common.h"
Marcin Bukat0b296912012-03-04 15:34:29 +010049#include "rb-loader.h"
50#include "loader_strerror.h"
Rafaël Carré5d236b22010-05-27 09:41:46 +000051#include "version.h"
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +000052
53#include <stdarg.h>
54
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +000055/* Maximum allowed firmware image size. 10MB is more than enough */
56#define MAX_LOADSIZE (10*1024*1024)
57
Linus Nielsen Feltzing62c768c2005-07-09 07:46:42 +000058#define DRAM_START 0x31000000
59
Miika Pekkarinen886c3022007-01-13 08:16:02 +000060#ifdef HAVE_EEPROM_SETTINGS
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000061static bool recovery_mode = false;
Miika Pekkarinen886c3022007-01-13 08:16:02 +000062#endif
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000063
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000064/* Reset the cookie for the crt0 crash check */
65inline void __reset_cookie(void)
66{
67 asm(" move.l #0,%d0");
68 asm(" move.l %d0,0x10017ffc");
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +000069}
70
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000071void start_iriver_fw(void)
72{
73 asm(" move.w #0x2700,%sr");
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000074 __reset_cookie();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000075 asm(" movec.l %d0,%vbr");
76 asm(" move.l 0,%sp");
77 asm(" lea.l 8,%a0");
78 asm(" jmp (%a0)");
79}
80
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000081void start_firmware(void)
82{
83 asm(" move.w #0x2700,%sr");
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000084 __reset_cookie();
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +000085 asm(" move.l %0,%%d0" :: "i"(DRAM_START));
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000086 asm(" movec.l %d0,%vbr");
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +000087 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START));
88 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4)));
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000089 asm(" jmp (%a0)");
90}
91
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +000092#ifdef IRIVER_H100_SERIES
93void start_flashed_romimage(void)
94{
95 uint8_t *src = (uint8_t *)FLASH_ROMIMAGE_ENTRY;
96 int *reset_vector;
97
98 if (!detect_flashed_romimage())
99 return ;
100
101 reset_vector = (int *)(&src[sizeof(struct flash_header)+4]);
102
103 asm(" move.w #0x2700,%sr");
104 __reset_cookie();
105
106 asm(" move.l %0,%%d0" :: "i"(DRAM_START));
107 asm(" movec.l %d0,%vbr");
108 asm(" move.l %0,%%sp" :: "m"(reset_vector[0]));
109 asm(" move.l %0,%%a0" :: "m"(reset_vector[1]));
110 asm(" jmp (%a0)");
111
112 /* Failure */
113 power_off();
114}
115
116void start_flashed_ramimage(void)
117{
118 struct flash_header hdr;
119 unsigned char *buf = (unsigned char *)DRAM_START;
120 uint8_t *src = (uint8_t *)FLASH_RAMIMAGE_ENTRY;
121
122 if (!detect_flashed_ramimage())
123 return;
124
125 /* Load firmware from flash */
126 cpu_boost(true);
127 memcpy(&hdr, src, sizeof(struct flash_header));
128 src += sizeof(struct flash_header);
129 memcpy(buf, src, hdr.length);
130 cpu_boost(false);
131
132 start_firmware();
133
134 /* Failure */
135 power_off();
136}
137#endif /* IRIVER_H100_SERIES */
138
139void shutdown(void)
140{
141 printf("Shutting down...");
142#ifdef HAVE_EEPROM_SETTINGS
143 /* Reset the rockbox crash check. */
144 firmware_settings.bl_version = 0;
145 eeprom_settings_store();
146#endif
147
148 /* We need to gracefully spin down the disk to prevent clicks. */
149 if (ide_powered())
150 {
151 /* Make sure ATA has been initialized. */
Frank Gevaerts2f8a0082008-11-01 16:14:28 +0000152 storage_init();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000153
154 /* And put the disk into sleep immediately. */
Frank Gevaerts2f8a0082008-11-01 16:14:28 +0000155 storage_sleepnow();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000156 }
157
158 sleep(HZ*2);
159
160 /* Backlight OFF */
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100161 backlight_hw_off();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000162#ifdef HAVE_REMOTE_LCD
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100163 remote_backlight_hw_off();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000164#endif
165
166 __reset_cookie();
167 power_off();
168}
169
170/* Print the battery voltage (and a warning message). */
171void check_battery(void)
172{
Jens Arnold0fac4922007-08-17 06:45:18 +0000173 int battery_voltage, batt_int, batt_frac;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000174
Thomas Martitzc1bd9b02012-01-03 23:44:38 +0000175 battery_voltage = _battery_voltage();
Jens Arnold0fac4922007-08-17 06:45:18 +0000176 batt_int = battery_voltage / 1000;
177 batt_frac = (battery_voltage % 1000) / 10;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000178
179 printf("Batt: %d.%02dV", batt_int, batt_frac);
180
181 if (battery_voltage <= 310)
182 {
183 printf("WARNING! BATTERY LOW!!");
184 sleep(HZ*2);
185 }
186}
187
188#ifdef HAVE_EEPROM_SETTINGS
189void initialize_eeprom(void)
190{
191 if (detect_original_firmware())
192 return ;
193
194 if (!eeprom_settings_init())
195 {
196 recovery_mode = true;
197 return ;
198 }
199
200 /* If bootloader version has not been reset, disk might
201 * not be intact. */
202 if (firmware_settings.bl_version || !firmware_settings.disk_clean)
203 {
204 firmware_settings.disk_clean = false;
205 recovery_mode = true;
206 }
207
208 firmware_settings.bl_version = EEPROM_SETTINGS_BL_MINVER;
209 eeprom_settings_store();
210}
211
212void try_flashboot(void)
213{
214 if (!firmware_settings.initialized)
215 return ;
216
217 switch (firmware_settings.bootmethod)
218 {
219 case BOOT_DISK:
220 return;
221
222 case BOOT_ROM:
223 start_flashed_romimage();
224 recovery_mode = true;
225 break;
226
227 case BOOT_RAM:
228 start_flashed_ramimage();
229 recovery_mode = true;
230 break;
231
232 default:
233 recovery_mode = true;
234 return;
235 }
236}
237
238static const char *options[] = {
239 "Boot from disk",
240 "Boot RAM image",
241 "Boot ROM image",
242 "Shutdown"
243};
244
245#define FAILSAFE_OPTIONS 4
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000246#define TIMEOUT (15*HZ)
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000247void failsafe_menu(void)
248{
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000249 long start_tick = current_tick;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000250 int option = 3;
251 int button;
252 int defopt = -1;
253 char buf[32];
254 int i;
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000255 extern int line;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000256
257 reset_screen();
Michael Sevakis95a4c3a2014-08-28 10:26:45 -0400258 printf("Bootloader %s", rbversion);
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000259 check_battery();
260 printf("=========================");
261 line += FAILSAFE_OPTIONS;
262 printf("");
263 printf(" [NAVI] to confirm.");
264 printf(" [REC] to set as default.");
265 printf("");
266
267 if (firmware_settings.initialized)
268 {
269 defopt = firmware_settings.bootmethod;
270 if (defopt < 0 || defopt >= FAILSAFE_OPTIONS)
271 defopt = option;
272 }
273
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000274 while (current_tick - start_tick < TIMEOUT)
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000275 {
276 /* Draw the menu. */
277 line = 3;
278 for (i = 0; i < FAILSAFE_OPTIONS; i++)
279 {
280 char *def = "[DEF]";
281 char *arrow = "->";
282
283 if (i != defopt)
284 def = "";
285 if (i != option)
286 arrow = " ";
287
288 printf("%s %s %s", arrow, options[i], def);
289 }
290
Thomas Martitz77dfff52010-05-06 21:37:03 +0000291 snprintf(buf, sizeof(buf), "Time left: %lds",
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000292 (TIMEOUT - (current_tick - start_tick)) / HZ);
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000293 lcd_puts(0, 10, buf);
294 lcd_update();
295 button = button_get_w_tmo(HZ);
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000296
297 if (button == BUTTON_NONE || button & SYS_EVENT)
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000298 continue ;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000299
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000300 start_tick = current_tick;
301
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000302 /* Ignore the ON/PLAY -button because it can cause trouble
303 with the RTC alarm mod. */
304 switch (button & ~(BUTTON_ON))
305 {
306 case BUTTON_UP:
307 case BUTTON_RC_REW:
308 if (option > 0)
309 option--;
310 break ;
311
312 case BUTTON_DOWN:
313 case BUTTON_RC_FF:
314 if (option < FAILSAFE_OPTIONS-1)
315 option++;
316 break ;
317
318 case BUTTON_SELECT:
319 case BUTTON_RC_ON:
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000320 goto execute;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000321
322 case BUTTON_REC:
323 case BUTTON_RC_REC:
324 if (firmware_settings.initialized)
325 {
326 firmware_settings.bootmethod = option;
327 eeprom_settings_store();
328 defopt = option;
329 }
330 break ;
331 }
332 }
333
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000334 execute:
335
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000336 lcd_puts(0, 10, "Executing command...");
337 lcd_update();
338 sleep(HZ);
339 reset_screen();
340
341 switch (option)
342 {
343 case BOOT_DISK:
344 return ;
345
346 case BOOT_RAM:
347 start_flashed_ramimage();
348 printf("Image not found");
349 break;
350
351 case BOOT_ROM:
352 start_flashed_romimage();
353 printf("Image not found");
354 break;
355 }
356
357 shutdown();
358}
359#endif
360
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000361/* get rid of a nasty humming sound during boot
362 -> RESET signal */
363inline static void __uda1380_reset_hi(void)
364{
365#ifdef HAVE_UDA1380
366 or_l(1<<29, &GPIO_OUT);
367 or_l(1<<29, &GPIO_ENABLE);
368 or_l(1<<29, &GPIO_FUNCTION);
369#endif
370}
371
372inline static void __uda1380_reset_lo(void)
373{
374#ifdef HAVE_UDA1380
375 and_l(~(1<<29), &GPIO_OUT);
376#endif
377}
378
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000379void main(void)
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000380{
381 int i;
382 int rc;
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000383 bool rc_on_button = false;
384 bool on_button = false;
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +0000385 bool rec_button = false;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000386 bool hold_status = false;
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000387 int data;
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000388 extern int line; /* From common.c */
389 extern int remote_line; /* From common.c */
Linus Nielsen Feltzingec549ec2007-02-22 21:38:59 +0000390
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000391 /* We want to read the buttons as early as possible, before the user
392 releases the ON button */
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000393
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000394 /* Set GPIO33, GPIO37, GPIO38 and GPIO52 as general purpose inputs
395 (The ON and Hold buttons on the main unit and the remote) */
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +0000396 or_l(0x00100062, &GPIO1_FUNCTION);
397 and_l(~0x00100062, &GPIO1_ENABLE);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000398
399 data = GPIO1_READ;
400 if ((data & 0x20) == 0)
401 on_button = true;
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000402
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000403 if ((data & 0x40) == 0)
404 rc_on_button = true;
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000405
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000406 /* Set the default state of the hard drive power to OFF */
407 ide_power_enable(false);
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000408
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000409 power_init();
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000410
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000411 /* Turn off if neither ON button is pressed */
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000412 if (!(on_button || rc_on_button))
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000413 {
414 __reset_cookie();
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000415 power_off();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000416 }
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000417
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000418 __uda1380_reset_hi();
419
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000420 /* Start with the main backlight OFF. */
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100421 backlight_hw_init();
422 backlight_hw_off();
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000423
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000424 /* Remote backlight ON */
425#ifdef HAVE_REMOTE_LCD
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100426 remote_backlight_hw_on();
Linus Nielsen Feltzingb68cb9b2005-12-03 00:54:59 +0000427#endif
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000428
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000429 system_init();
430 kernel_init();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000431
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000432 __uda1380_reset_lo();
433
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000434#ifdef HAVE_ADJUSTABLE_CPU_FREQ
435 /* Set up waitstates for the peripherals */
436 set_cpu_frequency(0); /* PLL off */
Michael Sevakis0f5cb942006-11-06 18:07:30 +0000437#ifdef CPU_COLDFIRE
438 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
439#endif
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000440#endif
Michael Sevakisaf395f42008-03-26 01:50:41 +0000441 enable_irq();
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +0000442
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000443#ifdef HAVE_EEPROM_SETTINGS
444 initialize_eeprom();
445#endif
446
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000447 usb_init();
448 /* A small delay after usb_init is necessary to read the I/O port correctly
449 (if ports are read _immediately_ after the init). */
450 /* sleep(1); */
451
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000452 adc_init();
453 button_init();
454
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000455 /* Only check remote hold status if remote power button was actually used. */
456 if (rc_on_button)
457 {
458 lcd_remote_init();
459
460 /* Allow the button driver to check the buttons */
461 sleep(HZ/50);
462
463 if (remote_button_hold())
464 hold_status = true;
465 }
466
467 /* Check main hold switch status too. */
468 if (on_button && button_hold())
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000469 {
470 hold_status = true;
471 }
472
Linus Nielsen Feltzingff179052007-03-02 11:28:23 +0000473 /* Power on the hard drive early, to speed up the loading. */
Miika Pekkarinen20171c12007-01-13 09:08:18 +0000474 if (!hold_status
475# ifdef HAVE_EEPROM_SETTINGS
476 && !recovery_mode
477# endif
478 )
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000479 {
480 ide_power_enable(true);
481 }
482
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000483# ifdef HAVE_EEPROM_SETTINGS
Dave Chapman16723502007-09-04 08:03:07 +0000484 if (!hold_status && (usb_detect() != USB_INSERTED) && !recovery_mode)
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000485 try_flashboot();
Miika Pekkarinen20171c12007-01-13 09:08:18 +0000486# endif
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000487
488 backlight_init();
Christian Gmeiner21ac3112007-11-20 12:09:59 +0000489
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000490
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000491 lcd_init();
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000492
493 if (!rc_on_button)
494 lcd_remote_init();
495
496 /* Bootloader uses simplified backlight thread, so we need to enable
497 remote display here. */
498 if (remote_detect())
499 lcd_remote_on();
500
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000501 font_init();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000502
503 lcd_setfont(FONT_SYSFIXED);
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000504
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000505 printf("Rockbox boot loader");
Michael Sevakis95a4c3a2014-08-28 10:26:45 -0400506 printf("Version %s", rbversion);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000507
Miika Pekkarinen698113d2008-02-09 15:06:09 +0000508 /* No need to wait here more because lcd_init and others already do that. */
509 // sleep(HZ/50); /* Allow the button driver to check the buttons */
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000510 rec_button = ((button_status() & BUTTON_REC) == BUTTON_REC)
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +0000511 || ((button_status() & BUTTON_RC_REC) == BUTTON_RC_REC);
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000512
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000513 check_battery();
514
Miika Pekkarinen22860a92006-08-11 19:59:16 +0000515 /* Don't start if the Hold button is active on the device you
516 are starting with */
Dave Chapman16723502007-09-04 08:03:07 +0000517 if ((usb_detect() != USB_INSERTED) && (hold_status
Miika Pekkarinen20171c12007-01-13 09:08:18 +0000518#ifdef HAVE_EEPROM_SETTINGS
519 || recovery_mode
520#endif
521 ))
Miika Pekkarinen22860a92006-08-11 19:59:16 +0000522 {
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000523 if (detect_original_firmware())
524 {
525 printf("Hold switch on");
526 shutdown();
527 }
528
Miika Pekkarinen20171c12007-01-13 09:08:18 +0000529#ifdef HAVE_EEPROM_SETTINGS
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000530 failsafe_menu();
Miika Pekkarinen22860a92006-08-11 19:59:16 +0000531#endif
Miika Pekkarinen22860a92006-08-11 19:59:16 +0000532 }
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000533
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000534 /* Holding REC while starting runs the original firmware */
535 if (detect_original_firmware() && rec_button)
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +0000536 {
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000537 printf("Starting original firmware...");
538 start_iriver_fw();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000539 }
540
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000541 /* A hack to enter USB mode without using the USB thread */
Dave Chapman16723502007-09-04 08:03:07 +0000542 if(usb_detect() == USB_INSERTED)
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000543 {
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000544 const char msg[] = "Bootloader USB mode";
545 int w, h;
546 font_getstringsize(msg, &w, &h, FONT_SYSFIXED);
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000547 reset_screen();
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000548 lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, msg);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000549 lcd_update();
550
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000551#ifdef HAVE_REMOTE_LCD
552 lcd_remote_puts(0, 3, msg);
553 lcd_remote_update();
554#endif
555
Peter D'Hoyec4a59a22006-08-15 22:54:06 +0000556#ifdef HAVE_EEPROM_SETTINGS
Miika Pekkarinene1eb91b2006-08-09 12:04:13 +0000557 if (firmware_settings.initialized)
558 {
559 firmware_settings.disk_clean = false;
560 eeprom_settings_store();
561 }
562#endif
Linus Nielsen Feltzing237ff9e2007-02-28 00:06:35 +0000563 ide_power_enable(true);
Frank Gevaerts2f8a0082008-11-01 16:14:28 +0000564 storage_enable(false);
Linus Nielsen Feltzing237ff9e2007-02-28 00:06:35 +0000565 sleep(HZ/20);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000566 usb_enable(true);
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000567 cpu_idle_mode(true);
Dave Chapman16723502007-09-04 08:03:07 +0000568 while (usb_detect() == USB_INSERTED)
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000569 {
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000570 /* Print the battery status. */
571 line = 0;
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000572 remote_line = 0;
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000573 check_battery();
574
Frank Gevaerts2f8a0082008-11-01 16:14:28 +0000575 storage_spin(); /* Prevent the drive from spinning down */
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000576 sleep(HZ);
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000577
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000578 /* Backlight OFF */
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100579 backlight_hw_off();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000580 }
581
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000582 cpu_idle_mode(false);
Linus Nielsen Feltzing13103902005-07-19 11:03:00 +0000583 usb_enable(false);
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000584
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000585 reset_screen();
Linus Nielsen Feltzing13103902005-07-19 11:03:00 +0000586 lcd_update();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000587 }
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000588
Frank Gevaerts2f8a0082008-11-01 16:14:28 +0000589 rc = storage_init();
Linus Nielsen Feltzing237ff9e2007-02-28 00:06:35 +0000590 if(rc)
591 {
592 reset_screen();
593 printf("ATA error: %d", rc);
594 printf("Insert USB cable and press");
595 printf("a button");
596 while(!(button_get(true) & BUTTON_REL));
597 }
598
599
Michael Sevakis7d1a47c2013-08-05 22:02:45 -0400600 filesystem_init();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000601
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000602 rc = disk_mount_all();
603 if (rc<=0)
604 {
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000605 reset_screen();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000606 printf("No partition found");
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000607 while(button_get(true) != SYS_USB_CONNECTED) {};
608 }
609
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000610 printf("Loading firmware");
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000611 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE);
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000612 if(i < 0)
Marcin Bukat0b296912012-03-04 15:34:29 +0100613 printf("Error: %s", loader_strerror(i));
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000614
Marcin Bukat0b296912012-03-04 15:34:29 +0100615 if (i > 0)
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000616 start_firmware();
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000617
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000618 if (!detect_original_firmware())
Miika Pekkarinen973ee5d2006-09-04 16:06:11 +0000619 {
620 printf("No firmware found on disk");
Linus Nielsen Feltzing46597c92007-02-22 15:09:49 +0000621 sleep(HZ*2);
Miika Pekkarinen35b0c3f2007-01-12 20:45:37 +0000622 shutdown();
Miika Pekkarinen973ee5d2006-09-04 16:06:11 +0000623 }
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000624 else {
625 sleep(HZ*2);
Miika Pekkarinen973ee5d2006-09-04 16:06:11 +0000626 start_iriver_fw();
Linus Nielsen Feltzing343c4282007-02-28 08:40:37 +0000627 }
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000628}
629
630/* These functions are present in the firmware library, but we reimplement
631 them here because the originals do a lot more than we want */
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000632void screen_dump(void)
633{
634}
Linus Nielsen Feltzingff179052007-03-02 11:28:23 +0000635
636int usb_screen(void)
637{
638 return 0;
639}
640
641unsigned short *bidi_l2v(const unsigned char *str, int orientation)
642{
643 static unsigned short utf16_buf[SCROLL_LINE_SIZE];
644 unsigned short *target;
645 (void)orientation;
646
647 target = utf16_buf;
648
649 while (*str)
650 str = utf8decode(str, target++);
651 *target = 0;
652 return utf16_buf;
653}