Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

x1000: Unified bootloader

Change-Id: Ib1f2ca2a376866c61dd1bd62abd6e31210d11e5c

+491 -361
+1 -1
bootloader/SOURCES
··· 90 90 sansaconnect.c 91 91 show_logo.c 92 92 #elif defined(FIIO_M3K) 93 - fiiom3k.c 93 + x1000.c 94 94 #endif
-360
bootloader/fiiom3k.c
··· 1 - /*************************************************************************** 2 - * __________ __ ___. 3 - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 - * \/ \/ \/ \/ \/ 8 - * $Id$ 9 - * 10 - * Copyright (C) 2021 Aidan MacDonald 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 - 22 - #include "system.h" 23 - #include "core_alloc.h" 24 - #include "kernel/kernel-internal.h" 25 - #include "i2c.h" 26 - #include "power.h" 27 - #include "lcd.h" 28 - #include "font.h" 29 - #include "backlight.h" 30 - #include "backlight-target.h" 31 - #include "button.h" 32 - #include "storage.h" 33 - #include "file_internal.h" 34 - #include "disk.h" 35 - #include "usb.h" 36 - #include "rb-loader.h" 37 - #include "loader_strerror.h" 38 - #include "version.h" 39 - #include "installer-fiiom3k.h" 40 - #include "boot-x1000.h" 41 - #include "x1000/cpm.h" 42 - 43 - /* Load address where the binary needs to be placed */ 44 - extern unsigned char loadaddress[]; 45 - 46 - /* Fixed buffer to contain the loaded binary in memory */ 47 - extern unsigned char loadbuffer[]; 48 - extern unsigned char loadbufferend[]; 49 - #define MAX_LOAD_SIZE (loadbufferend - loadbuffer) 50 - 51 - void exec(void* dst, const void* src, int bytes) 52 - __attribute__((noreturn, section(".icode"))); 53 - 54 - void exec(void* dst, const void* src, int bytes) 55 - { 56 - memcpy(dst, src, bytes); 57 - commit_discard_idcache(); 58 - __asm__ __volatile__ ("jr %0\n" 59 - "nop\n" 60 - :: "r"(dst)); 61 - __builtin_unreachable(); 62 - } 63 - 64 - static bool lcd_inited = false; 65 - static bool usb_inited = false; 66 - static bool disk_inited = false; 67 - 68 - static void init_lcd(void) 69 - { 70 - if(lcd_inited) 71 - return; 72 - 73 - lcd_init(); 74 - font_init(); 75 - lcd_setfont(FONT_SYSFIXED); 76 - 77 - /* Clear screen before turning backlight on, otherwise we might 78 - * display random garbage on the screen */ 79 - lcd_clear_display(); 80 - lcd_update(); 81 - 82 - backlight_init(); 83 - 84 - lcd_inited = true; 85 - } 86 - 87 - static void put_version(void) 88 - { 89 - lcd_putsxy((LCD_WIDTH - (SYSFONT_WIDTH * strlen(rbversion))) / 2, 90 - (LCD_HEIGHT - SYSFONT_HEIGHT), rbversion); 91 - } 92 - 93 - static void do_splash2(int delay, const char* msg, const char* msg2) 94 - { 95 - init_lcd(); 96 - lcd_clear_display(); 97 - lcd_putsxy((LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, 98 - (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); 99 - if(msg2) { 100 - lcd_putsxy((LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg2))) / 2, 101 - (LCD_HEIGHT + 2*SYSFONT_HEIGHT) / 2, msg2); 102 - } 103 - 104 - put_version(); 105 - lcd_update(); 106 - sleep(delay); 107 - } 108 - 109 - static void do_splash(int delay, const char* msg) 110 - { 111 - do_splash2(delay, msg, NULL); 112 - } 113 - 114 - static void do_usb(void) 115 - { 116 - if(!usb_inited) { 117 - usb_init(); 118 - usb_start_monitoring(); 119 - usb_inited = true; 120 - } 121 - 122 - do_splash2(0, "Waiting for USB", "Press POWER to go back"); 123 - 124 - int btn; 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 - } 132 - 133 - do_splash(0, "USB mode"); 134 - usb_acknowledge(SYS_USB_CONNECTED_ACK); 135 - while(button_get(true) != SYS_USB_DISCONNECTED); 136 - 137 - do_splash(3*HZ, "USB disconnected"); 138 - } 139 - 140 - static 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 - 161 - static 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 - 185 - static 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 - 220 - static 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 - 330 - void main(void) 331 - { 332 - bool recovery_mode = false; 333 - 334 - if(get_boot_flag(BOOT_FLAG_USB_BOOT)) 335 - recovery_mode = true; 336 - 337 - system_init(); 338 - core_allocator_init(); 339 - kernel_init(); 340 - i2c_init(); 341 - power_init(); 342 - button_init(); 343 - enable_irq(); 344 - 345 - if(storage_init() < 0) { 346 - do_splash(3*HZ, "Failed to init storage"); 347 - power_off(); 348 - } 349 - 350 - filesystem_init(); 351 - 352 - if(button_read_device() & BUTTON_VOL_UP) 353 - recovery_mode = true; 354 - 355 - if(!recovery_mode) 356 - do_boot(); 357 - 358 - /* If boot fails or user holds Vol+, go to recovery menu */ 359 - recovery_menu(); 360 - }
+490
bootloader/x1000.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2021 Aidan MacDonald 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 + 22 + /* Unified bootloader for all X1000 targets. This is a bit messy. 23 + * 24 + * Features: 25 + * - Text based user interface 26 + * - USB mass storage access 27 + * - Bootloader installation / backup / restore 28 + * 29 + * Possible future improvements: 30 + * - Allow booting original firmware from the UI 31 + */ 32 + 33 + #include "system.h" 34 + #include "core_alloc.h" 35 + #include "kernel/kernel-internal.h" 36 + #include "i2c.h" 37 + #include "power.h" 38 + #include "lcd.h" 39 + #include "font.h" 40 + #include "backlight.h" 41 + #include "backlight-target.h" 42 + #include "button.h" 43 + #include "storage.h" 44 + #include "file_internal.h" 45 + #include "disk.h" 46 + #include "usb.h" 47 + #include "rb-loader.h" 48 + #include "loader_strerror.h" 49 + #include "version.h" 50 + #include "boot-x1000.h" 51 + #include <stddef.h> 52 + #include <stdbool.h> 53 + #include <string.h> 54 + #include <stdio.h> 55 + #include <stdarg.h> 56 + 57 + #ifdef FIIO_M3K 58 + # include "installer-fiiom3k.h" 59 + #endif 60 + 61 + #if defined(FIIO_M3K) 62 + # define BL_RECOVERY BUTTON_VOL_UP 63 + # define BL_UP BUTTON_VOL_UP 64 + # define BL_DOWN BUTTON_VOL_DOWN 65 + # define BL_SELECT BUTTON_PLAY 66 + # define BL_QUIT BUTTON_POWER 67 + # define BL_UP_NAME "VOL+" 68 + # define BL_DOWN_NAME "VOL-" 69 + # define BL_SELECT_NAME "PLAY" 70 + # define BL_QUIT_NAME "POWER" 71 + #else 72 + # error "Missing keymap!" 73 + #endif 74 + 75 + enum { 76 + MENUITEM_HEADING, 77 + MENUITEM_ACTION, 78 + }; 79 + 80 + struct menuitem { 81 + int type; 82 + const char* text; 83 + void(*action)(void); 84 + }; 85 + 86 + void clearscreen(void); 87 + void putversion(void); 88 + void putcenter_y(int y, const char* msg); 89 + void putcenter_line(int line, const char* msg); 90 + void splash2(long delay, const char* msg, const char* msg2); 91 + void splash(long delay, const char* msg); 92 + 93 + void init_lcd(void); 94 + void init_usb(void); 95 + int init_disk(void); 96 + 97 + void recovery_menu(void) __attribute__((noreturn)); 98 + 99 + void boot_rockbox(void); 100 + void usb_mode(void); 101 + void shutdown(void); 102 + void reboot(void); 103 + void bootloader_install(void); 104 + void bootloader_backup(void); 105 + void bootloader_restore(void); 106 + 107 + /* Defines the recovery menu contents */ 108 + const struct menuitem recovery_items[] = { 109 + {MENUITEM_HEADING, "System", NULL}, 110 + {MENUITEM_ACTION, "Start Rockbox", &boot_rockbox}, 111 + {MENUITEM_ACTION, "USB mode", &usb_mode}, 112 + {MENUITEM_ACTION, "Shutdown", &shutdown}, 113 + {MENUITEM_ACTION, "Reboot", &reboot}, 114 + {MENUITEM_HEADING, "Bootloader", NULL}, 115 + {MENUITEM_ACTION, "Install or update", &bootloader_install}, 116 + {MENUITEM_ACTION, "Backup", &bootloader_backup}, 117 + {MENUITEM_ACTION, "Restore", &bootloader_restore}, 118 + }; 119 + 120 + /* Final load address of rockbox binary. 121 + * NOTE: this is really the load address of the bootloader... it relies 122 + * on the fact that bootloader and app are linked at the same address. */ 123 + extern unsigned char loadaddress[]; 124 + 125 + /* Temp buffer to contain the binary in memory */ 126 + extern unsigned char loadbuffer[]; 127 + extern unsigned char loadbufferend[]; 128 + #define MAX_LOAD_SIZE (loadbufferend - loadbuffer) 129 + 130 + /* Flags to indicate if hardware was already initialized */ 131 + bool lcd_inited = false; 132 + bool usb_inited = false; 133 + bool disk_inited = false; 134 + 135 + /* Jump to loaded binary */ 136 + void exec(void* dst, const void* src, size_t bytes) 137 + __attribute__((noinline, noreturn, section(".icode"))); 138 + 139 + void exec(void* dst, const void* src, size_t bytes) 140 + { 141 + memcpy(dst, src, bytes); 142 + commit_discard_idcache(); 143 + 144 + typedef void(*entry_fn)(void) __attribute__((noreturn)); 145 + entry_fn fn = (entry_fn)dst; 146 + fn(); 147 + } 148 + 149 + void clearscreen(void) 150 + { 151 + init_lcd(); 152 + lcd_clear_display(); 153 + putversion(); 154 + } 155 + 156 + void putversion(void) 157 + { 158 + int x = (LCD_WIDTH - SYSFONT_WIDTH*strlen(rbversion)) / 2; 159 + int y = LCD_HEIGHT - SYSFONT_HEIGHT; 160 + lcd_putsxy(x, y, rbversion); 161 + } 162 + 163 + void putcenter_y(int y, const char* msg) 164 + { 165 + int x = (LCD_WIDTH - SYSFONT_WIDTH*strlen(msg)) / 2; 166 + lcd_putsxy(x, y, msg); 167 + } 168 + 169 + void putcenter_line(int line, const char* msg) 170 + { 171 + int y = LCD_HEIGHT/2 + (line - 1)*SYSFONT_HEIGHT; 172 + putcenter_y(y, msg); 173 + } 174 + 175 + void splash2(long delay, const char* msg, const char* msg2) 176 + { 177 + clearscreen(); 178 + putcenter_line(0, msg); 179 + if(msg2) 180 + putcenter_line(1, msg2); 181 + lcd_update(); 182 + sleep(delay); 183 + } 184 + 185 + void splash(long delay, const char* msg) 186 + { 187 + splash2(delay, msg, NULL); 188 + } 189 + 190 + void init_lcd(void) 191 + { 192 + if(lcd_inited) 193 + return; 194 + 195 + lcd_init(); 196 + font_init(); 197 + lcd_setfont(FONT_SYSFIXED); 198 + 199 + /* Clear screen before turning backlight on, otherwise we might 200 + * display random garbage on the screen */ 201 + lcd_clear_display(); 202 + lcd_update(); 203 + 204 + backlight_init(); 205 + 206 + lcd_inited = true; 207 + } 208 + 209 + /* TODO: This does not work properly after a USB boot. 210 + * 211 + * The USB core is not properly reset by just re-initializing it, and I can't 212 + * figure out how to make it work. Setting the DWC_DCTL.SDIS bit will force a 213 + * disconnect (the usb-designware driver does this already as part of its init 214 + * but it doesn't seem to cause a disconnect). 215 + * 216 + * But the host still doesn't detect us properly when we reconnect. Linux gives 217 + * messages "usb 1-3: config 1 has no interfaces?" in dmesg and no mass storage 218 + * interfaces show up. 219 + * 220 + * Re-plugging the cable seems to reset everything to a working state and there 221 + * are no issues, but that's annoying. 222 + */ 223 + void init_usb(void) 224 + { 225 + if(usb_inited) 226 + return; 227 + 228 + usb_init(); 229 + usb_start_monitoring(); 230 + usb_inited = true; 231 + } 232 + 233 + int init_disk(void) 234 + { 235 + if(disk_inited) 236 + return 0; 237 + 238 + button_clear_queue(); 239 + while(!storage_present(IF_MD(0))) { 240 + splash2(0, "Insert SD card", "Press " BL_QUIT_NAME " for recovery"); 241 + if(button_get_w_tmo(HZ/4) == BL_QUIT) 242 + return -1; 243 + } 244 + 245 + if(disk_mount_all() <= 0) { 246 + splash(5*HZ, "Cannot mount disk"); 247 + return -1; 248 + } 249 + 250 + disk_inited = true; 251 + return 0; 252 + } 253 + 254 + void put_help_line(int line, const char* str1, const char* str2) 255 + { 256 + int width = LCD_WIDTH / SYSFONT_WIDTH; 257 + lcd_puts(0, line, str1); 258 + lcd_puts(width - strlen(str2), line, str2); 259 + } 260 + 261 + void recovery_menu(void) 262 + { 263 + const int n_items = sizeof(recovery_items)/sizeof(struct menuitem); 264 + 265 + int selection = 0; 266 + while(recovery_items[selection].type != MENUITEM_ACTION) 267 + ++selection; 268 + 269 + while(1) { 270 + clearscreen(); 271 + putcenter_y(0, "Rockbox recovery menu"); 272 + 273 + int top_line = 2; 274 + 275 + /* draw the menu */ 276 + for(int i = 0; i < n_items; ++i) { 277 + switch(recovery_items[i].type) { 278 + case MENUITEM_HEADING: 279 + lcd_putsf(0, top_line+i, "[%s]", recovery_items[i].text); 280 + break; 281 + 282 + case MENUITEM_ACTION: 283 + lcd_puts(3, top_line+i, recovery_items[i].text); 284 + break; 285 + 286 + default: 287 + break; 288 + } 289 + } 290 + 291 + /* draw the selection marker */ 292 + lcd_puts(0, top_line+selection, "=>"); 293 + 294 + /* draw the help text */ 295 + int line = (LCD_HEIGHT - SYSFONT_HEIGHT)/SYSFONT_HEIGHT - 3; 296 + put_help_line(line++, BL_DOWN_NAME "/" BL_UP_NAME, "move cursor"); 297 + put_help_line(line++, BL_SELECT_NAME, "select item"); 298 + put_help_line(line++, BL_QUIT_NAME, "power off"); 299 + 300 + lcd_update(); 301 + 302 + /* handle input */ 303 + button_clear_queue(); 304 + switch(button_get(true)) { 305 + case BL_SELECT: { 306 + if(recovery_items[selection].action) 307 + recovery_items[selection].action(); 308 + } break; 309 + 310 + case BL_UP: 311 + for(int i = selection-1; i >= 0; --i) { 312 + if(recovery_items[i].action) { 313 + selection = i; 314 + break; 315 + } 316 + } 317 + break; 318 + 319 + case BL_DOWN: 320 + for(int i = selection+1; i < n_items; ++i) { 321 + if(recovery_items[i].action) { 322 + selection = i; 323 + break; 324 + } 325 + } 326 + break; 327 + 328 + case BL_QUIT: 329 + shutdown(); 330 + break; 331 + 332 + default: 333 + break; 334 + } 335 + } 336 + } 337 + 338 + void boot_rockbox(void) 339 + { 340 + if(init_disk() != 0) 341 + return; 342 + 343 + int rc = load_firmware(loadbuffer, BOOTFILE, MAX_LOAD_SIZE); 344 + if(rc <= 0) { 345 + splash2(5*HZ, "Error loading Rockbox", loader_strerror(rc)); 346 + return; 347 + } 348 + 349 + if(lcd_inited) 350 + backlight_hw_off(); 351 + 352 + disable_irq(); 353 + exec(loadaddress, loadbuffer, rc); 354 + } 355 + 356 + void usb_mode(void) 357 + { 358 + init_usb(); 359 + splash2(0, "Waiting for USB", "Press " BL_QUIT_NAME " to go back"); 360 + 361 + while(1) { 362 + int btn = button_get(true); 363 + if(btn == SYS_USB_CONNECTED) 364 + break; 365 + else if(btn == BL_QUIT) 366 + return; 367 + } 368 + 369 + splash(0, "USB mode"); 370 + usb_acknowledge(SYS_USB_CONNECTED_ACK); 371 + while(button_get(true) != SYS_USB_DISCONNECTED); 372 + 373 + splash(3*HZ, "USB disconnected"); 374 + } 375 + 376 + void shutdown(void) 377 + { 378 + splash(HZ, "Shutting down"); 379 + power_off(); 380 + while(1); 381 + } 382 + 383 + void reboot(void) 384 + { 385 + splash(HZ, "Rebooting"); 386 + system_reboot(); 387 + while(1); 388 + } 389 + 390 + /* TODO: clean this up, make the installer generic as well */ 391 + enum { 392 + INSTALL, 393 + BACKUP, 394 + RESTORE, 395 + }; 396 + 397 + #ifdef FIIO_M3K 398 + void bootloader_action(int which) 399 + { 400 + if(init_disk() != 0) { 401 + splash2(5*HZ, "Install aborted", "Cannot access SD card"); 402 + return; 403 + } 404 + 405 + const char* msg; 406 + switch(which) { 407 + case INSTALL: msg = "Installing"; break; 408 + case BACKUP: msg = "Backing up"; break; 409 + case RESTORE: msg = "Restoring"; break; 410 + default: return; /* can't happen */ 411 + } 412 + 413 + splash(0, msg); 414 + 415 + int rc; 416 + switch(which) { 417 + case INSTALL: rc = install_boot("/bootloader.m3k"); break; 418 + case BACKUP: rc = backup_boot("/fiiom3k-boot.bin"); break; 419 + case RESTORE: rc = restore_boot("/fiiom3k-boot.bin"); break; 420 + default: return; 421 + } 422 + 423 + static char buf[64]; 424 + snprintf(buf, sizeof(buf), "Failed! Error: %d", rc); 425 + const char* msg1 = rc == 0 ? "Success" : buf; 426 + const char* msg2 = "Press " BL_QUIT_NAME " to continue"; 427 + splash2(0, msg1, msg2); 428 + 429 + button_clear_queue(); 430 + while(button_get(true) != BL_QUIT); 431 + } 432 + #else 433 + void bootloader_action(int which) 434 + { 435 + (void)which; 436 + splash(5*HZ, "Not implemented!"); 437 + } 438 + #endif 439 + 440 + void bootloader_install(void) 441 + { 442 + bootloader_action(INSTALL); 443 + } 444 + 445 + void bootloader_backup(void) 446 + { 447 + bootloader_action(BACKUP); 448 + } 449 + 450 + void bootloader_restore(void) 451 + { 452 + bootloader_action(RESTORE); 453 + } 454 + 455 + void main(void) 456 + { 457 + system_init(); 458 + core_allocator_init(); 459 + kernel_init(); 460 + i2c_init(); 461 + power_init(); 462 + button_init(); 463 + enable_irq(); 464 + 465 + if(storage_init() < 0) { 466 + splash(5*HZ, "storage_init() failed"); 467 + power_off(); 468 + } 469 + 470 + filesystem_init(); 471 + 472 + /* If USB booting, the user probably needs to enter recovery mode; 473 + * let's not force them to hold down the recovery key. */ 474 + bool recovery_mode = get_boot_flag(BOOT_FLAG_USB_BOOT); 475 + 476 + #ifdef HAVE_BUTTON_DATA 477 + int bdata; 478 + if(button_read_device(&bdata) & BL_RECOVERY) 479 + #else 480 + if(button_read_device() & BL_RECOVERY) 481 + #endif 482 + recovery_mode = true; 483 + 484 + /* If boot fails, it will return and continue on below */ 485 + if(!recovery_mode) 486 + boot_rockbox(); 487 + 488 + /* This function does not return. */ 489 + recovery_menu(); 490 + }