A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 274 lines 6.9 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2009 by Dave Chapman 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 <stdlib.h> 23#include <stdio.h> 24#include <stdarg.h> 25#include <string.h> 26 27#include "config.h" 28 29#include "inttypes.h" 30#include "cpu.h" 31#include "system.h" 32#include "lcd.h" 33#include "i2c-s5l8700.h" 34#include "../kernel-internal.h" 35#include "file_internal.h" 36#include "storage.h" 37#include "disk.h" 38#include "font.h" 39#include "backlight.h" 40#include "backlight-target.h" 41#include "button.h" 42#include "panic.h" 43#include "power.h" 44#include "file.h" 45#include "common.h" 46#include "rb-loader.h" 47#include "loader_strerror.h" 48#include "version.h" 49 50/* Safety measure - maximum allowed firmware image size. 51 The largest known current (October 2009) firmware is about 6.2MB so 52 we set this to 8MB. 53*/ 54#define MAX_LOADSIZE (8*1024*1024) 55 56/* The buffer to load the firmware into - use an uncached alias of 0x08000000 */ 57unsigned char *loadbuffer = (unsigned char *)0x48000000; 58 59extern int line; 60 61void fatal_error(void) 62{ 63 extern int line; 64 bool holdstatus=false; 65 66 /* System font is 6 pixels wide */ 67 printf("Hold MENU+SELECT to"); 68 printf("reboot then SELECT+PLAY"); 69 printf("for disk mode"); 70 lcd_update(); 71 72 while (1) { 73 if (button_hold() != holdstatus) { 74 if (button_hold()) { 75 holdstatus=true; 76 lcd_puts(0, line, "Hold switch on!"); 77 } else { 78 holdstatus=false; 79 lcd_puts(0, line, " "); 80 } 81 lcd_update(); 82 } 83 } 84} 85 86static void aes_decrypt(void* data, uint32_t size) 87{ 88 uint32_t ptr, i; 89 uint32_t go = 1; 90 91 PWRCONEXT &= ~0x400; 92 AESTYPE = 1; 93 AESUNKREG0 = 1; 94 AESUNKREG0 = 0; 95 AESCONTROL = 1; 96 AESKEYLEN = 8; 97 AESOUTSIZE = size; 98 AESAUXSIZE = 0x10; 99 AESINSIZE = 0x10; 100 AESSIZE3 = 0x10; 101 for (ptr = (size >> 2) - 4; ; ptr -= 4) 102 { 103 AESOUTADDR = (uint32_t)data + (ptr << 2); 104 AESINADDR = (uint32_t)data + (ptr << 2); 105 AESAUXADDR = (uint32_t)data + (ptr << 2); 106 AESSTATUS = 6; 107 AESGO = go; 108 go = 3; 109 while ((AESSTATUS & 6) == 0); 110 if (ptr == 0) break; 111 for (i = 0; i < 4; i++) 112 ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4]; 113 } 114 AESCONTROL = 0; 115 PWRCONEXT |= 0x400; 116} 117 118static int readfw(char* filename, void* address, int* size) 119{ 120 int i; 121 uint32_t startsector = 0; 122 uint32_t buffer[0x200]; 123 124 if (nand_read_sectors(0, 1, buffer) != 0) 125 return -1; 126 127 if (*((uint16_t*)((uint32_t)buffer + 0x1FE)) != 0xAA55) 128 return -2; 129 130 for (i = 0x1C2; i < 0x200; i += 0x10) { 131 if (((uint8_t*)buffer)[i] == 0) { 132 startsector = *((uint16_t*)((uint32_t)buffer + i + 4)) 133 | (*((uint16_t*)((uint32_t)buffer + i + 6)) << 16); 134 break; 135 } 136 } 137 138 if (startsector == 0) 139 return -3; 140 141 if (nand_read_sectors(startsector, 1, buffer) != 0) 142 return -4; 143 144 if (buffer[0x40] != 0x5B68695D) 145 return -5; 146 147 if (nand_read_sectors(startsector + 1 + (buffer[0x41] >> 11), 1, buffer) != 0) 148 return -6; 149 150 for (i = 0; i < 0x1FE; i += 10) { 151 if (memcmp(&buffer[i], filename, 8) == 0) { 152 uint32_t filesector = startsector + 1 + (buffer[i + 3] >> 11); 153 *size = buffer[i + 4]; 154 155 if (nand_read_sectors(filesector, ((*size + 0x7FF) >> 11), address) != 0) 156 return -7; 157 158 /* Success! */ 159 return 0; 160 } 161 } 162 163 /* Nothing found */ 164 return -8; 165} 166 167void main(void) 168{ 169 int i; 170 int btn; 171 int size; 172 int rc; 173 bool button_was_held; 174 175 /* Check the button hold status as soon as possible - to 176 give the user maximum chance to turn it on in order to 177 reset the settings in rockbox. */ 178 button_was_held = button_hold(); 179 180 system_init(); 181 kernel_init(); 182 183 i2c_init(); 184 185 enable_irq(); 186 187 lcd_init(); 188 font_init(); 189 190 backlight_init(); /* Turns on backlight -- BUGFIX backlight_init MUST BE AFTER lcd_init */ 191 192 lcd_set_foreground(LCD_WHITE); 193 lcd_set_background(LCD_BLACK); 194 lcd_clear_display(); 195 196 button_init(); 197 198 btn = button_status(); 199 200 /* Enable bootloader messages */ 201 if (btn==BUTTON_RIGHT) 202 verbose = true; 203 204 lcd_setfont(FONT_SYSFIXED); 205 206 printf("Rockbox boot loader"); 207 printf("Version: %s", rbversion); 208 209 i = storage_init(); 210 211 if (i != 0) { 212 printf("ATA error: %d", i); 213 fatal_error(); 214 } 215 216 filesystem_init(); 217 218 rc = disk_mount_all(); 219 if (rc<=0) 220 { 221 printf("No partition found"); 222 fatal_error(); 223 } 224 225 if (button_was_held || (btn==BUTTON_MENU)) { 226 /* If either the hold switch was on, or the Menu button was held, then 227 try the Apple firmware */ 228 printf("Loading original firmware..."); 229 230 if ((rc = readfw("DNANkbso", loadbuffer, &size)) < 0) { 231 printf("readfw error %d",rc); 232 fatal_error(); 233 } 234 235 /* Now we need to decrypt it */ 236 printf("Decrypting %d bytes...",size); 237 238 aes_decrypt(loadbuffer, size); 239 } else { 240 printf("Loading Rockbox..."); 241 rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE); 242 243 if (rc <= EFILE_EMPTY) { 244 printf("Error!"); 245 printf("Can't load " BOOTFILE ": "); 246 printf(loader_strerror(rc)); 247 fatal_error(); 248 } 249 250 printf("Rockbox loaded."); 251 } 252 253 254 /* If we get here, we have a new firmware image at 0x08000000, run it */ 255 printf("Executing..."); 256 257 disable_irq(); 258 259 /* Remap the bootrom back to zero - that's how the NOR bootloader leaves 260 it. 261 */ 262 MIUCON &= ~1; 263 264 /* Disable caches and protection unit */ 265 asm volatile( 266 "mrc 15, 0, r0, c1, c0, 0 \n" 267 "bic r0, r0, #0x1000 \n" 268 "bic r0, r0, #0x5 \n" 269 "mcr 15, 0, r0, c1, c0, 0 \n" 270 ); 271 272 /* Branch to start of DRAM */ 273 asm volatile("ldr pc, =0x08000000"); 274}