diff options
Diffstat (limited to 'bootloader/iriver_h300.c')
-rw-r--r-- | bootloader/iriver_h300.c | 251 |
1 files changed, 248 insertions, 3 deletions
diff --git a/bootloader/iriver_h300.c b/bootloader/iriver_h300.c index ee344d4165..ff3c8de2af 100644 --- a/bootloader/iriver_h300.c +++ b/bootloader/iriver_h300.c | |||
@@ -43,11 +43,12 @@ | |||
43 | #include "power.h" | 43 | #include "power.h" |
44 | #include "powermgmt.h" | 44 | #include "powermgmt.h" |
45 | #include "file.h" | 45 | #include "file.h" |
46 | #include "eeprom_settings.h" | ||
47 | #include "rbunicode.h" | ||
46 | #include "pcf50606.h" | 48 | #include "pcf50606.h" |
47 | #include "common.h" | 49 | #include "common.h" |
48 | #include "rb-loader.h" | 50 | #include "rb-loader.h" |
49 | #include "loader_strerror.h" | 51 | #include "loader_strerror.h" |
50 | #include "rbunicode.h" | ||
51 | #include "isp1362.h" | 52 | #include "isp1362.h" |
52 | #include "version.h" | 53 | #include "version.h" |
53 | 54 | ||
@@ -62,6 +63,8 @@ | |||
62 | extern int line; | 63 | extern int line; |
63 | extern int remote_line; | 64 | extern int remote_line; |
64 | 65 | ||
66 | static bool recovery_mode = false; | ||
67 | |||
65 | /* Reset the cookie for the crt0 crash check */ | 68 | /* Reset the cookie for the crt0 crash check */ |
66 | inline void __reset_cookie(void) | 69 | inline void __reset_cookie(void) |
67 | { | 70 | { |
@@ -90,9 +93,57 @@ void start_firmware(void) | |||
90 | asm(" jmp (%a0)"); | 93 | asm(" jmp (%a0)"); |
91 | } | 94 | } |
92 | 95 | ||
96 | void start_flashed_romimage(void) | ||
97 | { | ||
98 | uint8_t *src = (uint8_t *)FLASH_ROMIMAGE_ENTRY; | ||
99 | uint32_t *reset_vector; | ||
100 | |||
101 | if (!detect_flashed_romimage()) | ||
102 | return ; | ||
103 | |||
104 | reset_vector = (uint32_t *)(&src[sizeof(struct flash_header)+sizeof(uint32_t)]); | ||
105 | |||
106 | asm(" move.w #0x2700,%sr"); | ||
107 | __reset_cookie(); | ||
108 | |||
109 | asm(" move.l %0,%%d0" :: "i"(DRAM_START)); | ||
110 | asm(" movec.l %d0,%vbr"); | ||
111 | asm(" move.l %0,%%sp" :: "m"(reset_vector[0])); | ||
112 | asm(" move.l %0,%%a0" :: "m"(reset_vector[1])); | ||
113 | asm(" jmp (%a0)"); | ||
114 | |||
115 | /* Failure */ | ||
116 | power_off(); | ||
117 | } | ||
118 | |||
119 | void start_flashed_ramimage(void) | ||
120 | { | ||
121 | struct flash_header hdr; | ||
122 | uint8_t *buf = (uint8_t *)DRAM_START; | ||
123 | uint8_t *src = (uint8_t *)FLASH_RAMIMAGE_ENTRY; | ||
124 | |||
125 | if (!detect_flashed_ramimage()) | ||
126 | return; | ||
127 | |||
128 | /* Load firmware from flash */ | ||
129 | cpu_boost(true); | ||
130 | memcpy(&hdr, src, sizeof(struct flash_header)); | ||
131 | src += sizeof(struct flash_header); | ||
132 | memcpy(buf, src, hdr.length); | ||
133 | cpu_boost(false); | ||
134 | |||
135 | start_firmware(); | ||
136 | |||
137 | /* Failure */ | ||
138 | power_off(); | ||
139 | } | ||
140 | |||
93 | void shutdown(void) | 141 | void shutdown(void) |
94 | { | 142 | { |
95 | printf("Shutting down..."); | 143 | printf("Shutting down..."); |
144 | /* Reset the rockbox crash check. */ | ||
145 | firmware_settings.bl_version = 0; | ||
146 | eeprom_settings_store(); | ||
96 | 147 | ||
97 | /* We need to gracefully spin down the disk to prevent clicks. */ | 148 | /* We need to gracefully spin down the disk to prevent clicks. */ |
98 | if (ide_powered()) | 149 | if (ide_powered()) |
@@ -106,6 +157,7 @@ void shutdown(void) | |||
106 | 157 | ||
107 | sleep(HZ*2); | 158 | sleep(HZ*2); |
108 | 159 | ||
160 | /* Backlight OFF */ | ||
109 | backlight_hw_off(); | 161 | backlight_hw_off(); |
110 | remote_backlight_hw_off(); | 162 | remote_backlight_hw_off(); |
111 | 163 | ||
@@ -131,6 +183,176 @@ void check_battery(void) | |||
131 | } | 183 | } |
132 | } | 184 | } |
133 | 185 | ||
186 | void initialize_eeprom(void) | ||
187 | { | ||
188 | if (detect_original_firmware()) | ||
189 | return ; | ||
190 | |||
191 | if (!eeprom_settings_init()) | ||
192 | { | ||
193 | recovery_mode = true; | ||
194 | return ; | ||
195 | } | ||
196 | |||
197 | /* If bootloader version has not been reset, disk might | ||
198 | * not be intact. */ | ||
199 | if (firmware_settings.bl_version || !firmware_settings.disk_clean) | ||
200 | { | ||
201 | firmware_settings.disk_clean = false; | ||
202 | recovery_mode = true; | ||
203 | } | ||
204 | |||
205 | firmware_settings.bl_version = EEPROM_SETTINGS_BL_MINVER; | ||
206 | eeprom_settings_store(); | ||
207 | } | ||
208 | |||
209 | void try_flashboot(void) | ||
210 | { | ||
211 | if (!firmware_settings.initialized) | ||
212 | return ; | ||
213 | |||
214 | switch (firmware_settings.bootmethod) | ||
215 | { | ||
216 | case BOOT_DISK: | ||
217 | return; | ||
218 | |||
219 | case BOOT_ROM: | ||
220 | start_flashed_romimage(); | ||
221 | recovery_mode = true; | ||
222 | break; | ||
223 | |||
224 | case BOOT_RAM: | ||
225 | start_flashed_ramimage(); | ||
226 | recovery_mode = true; | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | recovery_mode = true; | ||
231 | return; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | void failsafe_menu(void) | ||
236 | { | ||
237 | static const char *options[] = | ||
238 | { | ||
239 | "Boot from disk", | ||
240 | "Boot RAM image", | ||
241 | "Boot ROM image", | ||
242 | "Shutdown" | ||
243 | }; | ||
244 | const int FAILSAFE_OPTIONS = sizeof(options) / sizeof(*options); | ||
245 | const long TIMEOUT = 15 * HZ; | ||
246 | long start_tick = current_tick; | ||
247 | int option = 3; | ||
248 | int button; | ||
249 | int defopt = -1; | ||
250 | char buf[32]; | ||
251 | int i; | ||
252 | |||
253 | reset_screen(); | ||
254 | printf("Bootloader %s", rbversion); | ||
255 | check_battery(); | ||
256 | printf("========================="); | ||
257 | line += FAILSAFE_OPTIONS; | ||
258 | printf(""); | ||
259 | printf(" [NAVI] to confirm."); | ||
260 | printf(" [REC] to set as default."); | ||
261 | printf(""); | ||
262 | |||
263 | if (firmware_settings.initialized) | ||
264 | { | ||
265 | defopt = firmware_settings.bootmethod; | ||
266 | if (defopt < 0 || defopt >= FAILSAFE_OPTIONS) | ||
267 | defopt = option; | ||
268 | } | ||
269 | |||
270 | while (current_tick - start_tick < TIMEOUT) | ||
271 | { | ||
272 | /* Draw the menu. */ | ||
273 | line = 3; | ||
274 | for (i = 0; i < FAILSAFE_OPTIONS; i++) | ||
275 | { | ||
276 | char *def = "[DEF]"; | ||
277 | char *arrow = "->"; | ||
278 | |||
279 | if (i != defopt) | ||
280 | def = ""; | ||
281 | if (i != option) | ||
282 | arrow = " "; | ||
283 | |||
284 | printf("%s %s %s", arrow, options[i], def); | ||
285 | } | ||
286 | |||
287 | snprintf(buf, sizeof(buf), "Time left: %lds", | ||
288 | (TIMEOUT - (current_tick - start_tick)) / HZ); | ||
289 | lcd_puts(0, 10, buf); | ||
290 | lcd_update(); | ||
291 | button = button_get_w_tmo(HZ); | ||
292 | |||
293 | if (button == BUTTON_NONE || button & SYS_EVENT) | ||
294 | continue ; | ||
295 | |||
296 | start_tick = current_tick; | ||
297 | |||
298 | /* Ignore the ON/PLAY -button because it can cause trouble | ||
299 | with the RTC alarm mod. */ | ||
300 | switch (button & ~(BUTTON_ON)) | ||
301 | { | ||
302 | case BUTTON_UP: | ||
303 | case BUTTON_RC_REW: | ||
304 | if (option > 0) | ||
305 | option--; | ||
306 | break ; | ||
307 | |||
308 | case BUTTON_DOWN: | ||
309 | case BUTTON_RC_FF: | ||
310 | if (option < FAILSAFE_OPTIONS-1) | ||
311 | option++; | ||
312 | break ; | ||
313 | |||
314 | case BUTTON_SELECT: | ||
315 | case BUTTON_RC_ON: | ||
316 | goto execute; | ||
317 | |||
318 | case BUTTON_REC: | ||
319 | case BUTTON_RC_REC: | ||
320 | if (firmware_settings.initialized) | ||
321 | { | ||
322 | firmware_settings.bootmethod = option; | ||
323 | eeprom_settings_store(); | ||
324 | defopt = option; | ||
325 | } | ||
326 | break ; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | execute: | ||
331 | |||
332 | lcd_puts(0, 10, "Executing command..."); | ||
333 | lcd_update(); | ||
334 | sleep(HZ); | ||
335 | reset_screen(); | ||
336 | |||
337 | switch (option) | ||
338 | { | ||
339 | case BOOT_DISK: | ||
340 | return ; | ||
341 | |||
342 | case BOOT_RAM: | ||
343 | start_flashed_ramimage(); | ||
344 | printf("Image not found"); | ||
345 | break; | ||
346 | |||
347 | case BOOT_ROM: | ||
348 | start_flashed_romimage(); | ||
349 | printf("Image not found"); | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | shutdown(); | ||
354 | } | ||
355 | |||
134 | /* From the pcf50606 driver */ | 356 | /* From the pcf50606 driver */ |
135 | extern unsigned char pcf50606_intregs[3]; | 357 | extern unsigned char pcf50606_intregs[3]; |
136 | 358 | ||
@@ -187,6 +409,7 @@ void main(void) | |||
187 | backlight_hw_init(); | 409 | backlight_hw_init(); |
188 | backlight_hw_off(); | 410 | backlight_hw_off(); |
189 | 411 | ||
412 | /* Remote backlight ON */ | ||
190 | remote_backlight_hw_on(); | 413 | remote_backlight_hw_on(); |
191 | 414 | ||
192 | system_init(); | 415 | system_init(); |
@@ -197,11 +420,20 @@ void main(void) | |||
197 | coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS); | 420 | coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS); |
198 | enable_irq(); | 421 | enable_irq(); |
199 | 422 | ||
423 | initialize_eeprom(); | ||
424 | |||
200 | isp1362_init(); | 425 | isp1362_init(); |
201 | 426 | ||
202 | adc_init(); | 427 | adc_init(); |
203 | button_init(); | 428 | button_init(); |
204 | 429 | ||
430 | /* Power on the hard drive early, to speed up the loading. */ | ||
431 | if (!hold_status && !recovery_mode) | ||
432 | ide_power_enable(true); | ||
433 | |||
434 | if (!hold_status && (usb_detect() != USB_INSERTED) && !recovery_mode) | ||
435 | try_flashboot(); | ||
436 | |||
205 | lcd_init(); | 437 | lcd_init(); |
206 | lcd_remote_init(); | 438 | lcd_remote_init(); |
207 | font_init(); | 439 | font_init(); |
@@ -229,14 +461,16 @@ void main(void) | |||
229 | { | 461 | { |
230 | hold_status = true; | 462 | hold_status = true; |
231 | } | 463 | } |
232 | if (hold_status && !rtc_alarm && (usb_detect() != USB_INSERTED) && | 464 | if ((hold_status || recovery_mode) && !rtc_alarm && |
233 | !charger_inserted()) | 465 | (usb_detect() != USB_INSERTED) && !charger_inserted()) |
234 | { | 466 | { |
235 | if (detect_original_firmware()) | 467 | if (detect_original_firmware()) |
236 | { | 468 | { |
237 | printf("Hold switch on"); | 469 | printf("Hold switch on"); |
238 | shutdown(); | 470 | shutdown(); |
239 | } | 471 | } |
472 | |||
473 | failsafe_menu(); | ||
240 | } | 474 | } |
241 | 475 | ||
242 | /* Holding REC while starting runs the original firmware */ | 476 | /* Holding REC while starting runs the original firmware */ |
@@ -321,6 +555,12 @@ void main(void) | |||
321 | lcd_remote_puts(0, 3, msg); | 555 | lcd_remote_puts(0, 3, msg); |
322 | lcd_remote_update(); | 556 | lcd_remote_update(); |
323 | 557 | ||
558 | if (firmware_settings.initialized) | ||
559 | { | ||
560 | firmware_settings.disk_clean = false; | ||
561 | eeprom_settings_store(); | ||
562 | } | ||
563 | |||
324 | ide_power_enable(true); | 564 | ide_power_enable(true); |
325 | storage_enable(false); | 565 | storage_enable(false); |
326 | sleep(HZ/20); | 566 | sleep(HZ/20); |
@@ -351,6 +591,11 @@ void main(void) | |||
351 | usb_charge = false; | 591 | usb_charge = false; |
352 | } | 592 | } |
353 | 593 | ||
594 | /* boot from flash if that is the default */ | ||
595 | try_flashboot(); | ||
596 | if (recovery_mode) | ||
597 | printf("Falling back to boot from disk"); | ||
598 | |||
354 | rc = storage_init(); | 599 | rc = storage_init(); |
355 | if(rc) | 600 | if(rc) |
356 | { | 601 | { |