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.

echoplayer: load Rockbox from SD card in bootloader

To avoid problems with SDMMC DMA not being able to
access all SRAMs equally, the ELF binary is loaded
at the top of SDRAM and then copied into place.

Change-Id: Icf16d02bc15605539cbe781dd27709225abca8f9

authored by

Aidan MacDonald and committed by
Solomon Peachy
603c5bb2 7868e45e

+100 -2
+99 -2
bootloader/echoplayer.c
··· 26 26 #include "button.h" 27 27 #include "storage.h" 28 28 #include "disk.h" 29 + #include "file.h" 29 30 #include "file_internal.h" 30 31 #include "usb.h" 32 + #include "elf.h" 33 + #include "elf_loader.h" 31 34 #include "rbversion.h" 32 35 #include "system-echoplayer.h" 33 36 #include "gpio-stm32h7.h" 34 37 38 + #define SDRAM_SIZE (MEMORYSIZE * 1024 * 1024) 39 + 40 + /* Address where Rockbox .elf binary will be cached in RAM */ 41 + #define LOAD_SIZE (2 * 1024 * 1024) 42 + #define LOAD_BUFFER_ADDR (STM32_SDRAM1_BASE + SDRAM_SIZE - LOAD_SIZE) 43 + 35 44 /* Events for the monitor callback to signal the main thread */ 36 45 #define EV_POWER_PRESSED MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0) 37 46 #define EV_POWER_RELEASED MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1) ··· 44 53 #define USB_UNPLUGGED_ACTIVE_TIME (30 * HZ) 45 54 #define USB_UNPLUGGED_INACTIVE_TIME (3 * HZ) 46 55 56 + static const struct elf_memory_map rb_elf_mmap[] = { 57 + { 58 + .addr = STM32_ITCM_BASE, 59 + .size = STM32_ITCM_SIZE, 60 + .flags = PF_R | PF_X, 61 + }, 62 + { 63 + .addr = STM32_DTCM_BASE, 64 + .size = STM32_DTCM_SIZE, 65 + .flags = PF_R | PF_W, 66 + }, 67 + { 68 + .addr = STM32_SDRAM1_BASE, 69 + .size = SDRAM_SIZE - LOAD_SIZE, 70 + .flags = PF_R | PF_W | PF_X, 71 + }, 72 + }; 73 + 74 + static const struct elf_load_context rb_elf_ctx = { 75 + .mmap = rb_elf_mmap, 76 + .num_mmap = ARRAYLEN(rb_elf_mmap), 77 + }; 78 + 47 79 /* Power button monitor state */ 48 80 static bool pwr_curr_state; 49 81 static bool pwr_prev_state; ··· 75 107 /* Optional error message displayed on LCD */ 76 108 static const char *status_msg = NULL; 77 109 110 + /* Location of Rockbox ELF binary in memory */ 111 + static void *elf_load_addr = NULL; 112 + static size_t elf_load_size = 0; 113 + 78 114 /* Helper functions */ 79 115 static bool is_power_button_pressed(void) 80 116 { ··· 152 188 153 189 gpio_set_level(GPIO_CPU_POWER_ON, 1); 154 190 storage_enable(true); 191 + disk_mount_all(); 155 192 } 156 193 157 194 static void go_inactive(void) ··· 213 250 lcd_enable(true); 214 251 } 215 252 253 + static bool load_rockbox(void) 254 + { 255 + int fd = open(BOOTDIR "/" BOOTFILE, O_RDONLY); 256 + if (fd < 0) 257 + { 258 + status_msg = "Rockbox not found"; 259 + return false; 260 + } 261 + 262 + void *tmp_buf = (void *)LOAD_BUFFER_ADDR; 263 + size_t tmp_size = LOAD_SIZE; 264 + 265 + ssize_t ret = read(fd, tmp_buf, tmp_size); 266 + if (ret < 0) 267 + { 268 + status_msg = "I/O error loading Rockbox"; 269 + goto out; 270 + } 271 + 272 + if ((size_t)ret == tmp_size) 273 + { 274 + status_msg = "Rockbox binary too large"; 275 + goto out; 276 + } 277 + 278 + elf_load_addr = tmp_buf; 279 + elf_load_size = tmp_size; 280 + 281 + out: 282 + close(fd); 283 + return elf_load_addr != NULL; 284 + } 285 + 286 + static void launch_elf(void) 287 + { 288 + void *entrypoint = NULL; 289 + void (*entry_fn) (void) = NULL; 290 + 291 + if (elf_load_addr == NULL || elf_load_size == 0) 292 + return; 293 + 294 + int err = elf_loadmem(elf_load_addr, elf_load_size, &rb_elf_ctx, &entrypoint); 295 + if (err) 296 + { 297 + status_msg = "Failed to execute Rockbox"; 298 + return; 299 + } 300 + 301 + disk_unmount_all(); 302 + storage_enable(false); 303 + lcd_shutdown(); 304 + 305 + entry_fn = entrypoint; 306 + commit_discard_idcache(); 307 + disable_irq(); 308 + stm32_systick_disable(); 309 + 310 + entry_fn(); 311 + } 312 + 216 313 static void launch(void) 217 314 { 218 315 /* No-op if USB mode was requested */ 219 316 if (is_usbmode_button_pressed()) 220 317 return; 221 318 222 - /* TODO: load rockbox */ 223 - status_msg = "Can't boot RB yet!"; 319 + load_rockbox(); 320 + launch_elf(); 224 321 } 225 322 226 323 void main(void)
+1
firmware/export/config/echor1.h
··· 124 124 #define HAVE_HOTKEY 125 125 #define AB_REPEAT_ENABLE 126 126 #define HAVE_BOOTLOADER_SCREENDUMP 127 + #define HAVE_ELF