diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-07-10 19:05:29 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-07-11 15:39:40 +0100 |
commit | e9d228832ccbee7e486c45a51680c6f94ce1ab92 (patch) | |
tree | 494348b9ccd742fc5df3568cf0740062974172ef /bootloader/fiiom3k.c | |
parent | d6dcb996847b547e1e980884fbc06966293a7f6a (diff) | |
download | rockbox-e9d228832ccbee7e486c45a51680c6f94ce1ab92.tar.gz rockbox-e9d228832ccbee7e486c45a51680c6f94ce1ab92.zip |
x1000: Unified bootloader
Change-Id: Ib1f2ca2a376866c61dd1bd62abd6e31210d11e5c
Diffstat (limited to 'bootloader/fiiom3k.c')
-rw-r--r-- | bootloader/fiiom3k.c | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/bootloader/fiiom3k.c b/bootloader/fiiom3k.c deleted file mode 100644 index 42b3260e07..0000000000 --- a/bootloader/fiiom3k.c +++ /dev/null | |||
@@ -1,360 +0,0 @@ | |||
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 | } | ||