Index: bootloader/e200.c =================================================================== RCS file: /cvsroot/rockbox/bootloader/e200.c,v retrieving revision 1.5 diff -u -r1.5 e200.c --- bootloader/e200.c 16 Oct 2006 17:21:30 -0000 1.5 +++ bootloader/e200.c 5 Dec 2006 01:27:21 -0000 @@ -5,9 +5,12 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: e200.c,v 1.5 2006-10-16 17:21:30 dan_a Exp $ + * $Id: h10.c,v 1.4 2006-08-28 08:11:32 barrywardell Exp $ * - * Copyright (C) 2006 Daniel Stenberg + * Copyright (C) 2006 by Barry Wardell + * + * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing + * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -32,63 +35,202 @@ #include "font.h" #include "adc.h" #include "backlight.h" +#include "button.h" #include "panic.h" #include "power.h" #include "file.h" -static inline void blink(void) +/* Size of the buffer to store the loaded Rockbox/Sansa image */ +#define MAX_LOADSIZE (10*1024*1024) + +/* A buffer to load the iriver firmware or Rockbox into */ +unsigned char loadbuffer[MAX_LOADSIZE]; + +char version[] = APPSVERSION; + +#define DRAM_START 0x10000000 + +int line=0; + +/* Load original Sandisk firmware. This function expects a file called + "/.rockbox/OF.bin" on the player. It should be decrypted + and have the header stripped using mi4code. It reads the file in to a memory + buffer called buf. The rest of the loading is done in main() and crt0.S +*/ +int load_sandisk(unsigned char* buf) { - volatile unsigned int* ptr; + int fd; + int rc; + int len; + + fd = open("/.rockbox/OF.bin", O_RDONLY); + + len = filesize(fd); + + if (len > MAX_LOADSIZE) + return -6; + + rc = read(fd, buf, len); + if(rc < len) + return -4; + + close(fd); + return len; +} + +/* Load Rockbox firmware (rockbox.e200) */ +int load_rockbox(unsigned char* buf) +{ + int fd; + int rc; + int len; + unsigned long chksum; + char model[5]; + unsigned long sum; int i; - ptr = (volatile unsigned int*)0x70000020; + char str[80]; - *ptr &= ~(1 << 13); - for(i = 0; i < 0xfffff; i++) + fd = open("/.rockbox/" BOOTFILE, O_RDONLY); + if(fd < 0) { + fd = open("/" BOOTFILE, O_RDONLY); + if(fd < 0) + return -1; } - *ptr |= (1 << 13); - for(i = 0; i < 0xfffff; i++) - { + + len = filesize(fd) - 8; + + snprintf(str, sizeof(str), "Length: %x", len); + lcd_puts(0, line++ ,str); + lcd_update(); + + if (len > MAX_LOADSIZE) + return -6; + + lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); + + rc = read(fd, &chksum, 4); + chksum=betoh32(chksum); /* Rockbox checksums are big-endian */ + if(rc < 4) + return -2; + + snprintf(str, sizeof(str), "Checksum: %x", chksum); + lcd_puts(0, line++ ,str); + lcd_update(); + + rc = read(fd, model, 4); + if(rc < 4) + return -3; + + model[4] = 0; + + snprintf(str, sizeof(str), "Model name: %s", model); + lcd_puts(0, line++ ,str); + lcd_update(); + + lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); + + rc = read(fd, buf, len); + if(rc < len) + return -4; + + close(fd); + + sum = MODEL_NUMBER; + + for(i = 0;i < len;i++) { + sum += buf[i]; } + + snprintf(str, sizeof(str), "Sum: %x", sum); + lcd_puts(0, line++ ,str); + lcd_update(); + + if(sum != chksum) + return -5; + + return len; } -static inline void slow_blink(void) +void* main(void) { - volatile unsigned int* ptr; + char buf[256]; int i; - ptr = (volatile unsigned int*)0x70000020; + int rc; + unsigned short* identify_info; + struct partinfo* pinfo; - *ptr &= ~(1 << 13); - for(i = 0; i < (0xfffff); i++) - { - } - for(i = 0; i < (0xfffff); i++) - { - } - for(i = 0; i < (0xfffff); i++) - { - } + system_init(); + kernel_init(); + lcd_init(); + font_init(); - *ptr |= (1 << 13); - for(i = 0; i < (0xfffff); i++) + line=0; + + lcd_setfont(FONT_SYSFIXED); + + lcd_puts(0, line++, "Rockbox boot loader"); + snprintf(buf, sizeof(buf), "Version: 20%s", version); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "Sandisk Sansa E200"); + lcd_puts(0, line++, buf); + lcd_update(); + + i=ata_init(); + if (i==0) { + identify_info=ata_get_identify(); + /* Show model */ + for (i=0; i < 20; i++) { + ((unsigned short*)buf)[i]=htobe16(identify_info[i+27]); + } + buf[40]=0; + for (i=39; i && buf[i]==' '; i--) { + buf[i]=0; + } + lcd_puts(0, line++, buf); + lcd_update(); + } else { + snprintf(buf, sizeof(buf), "ATA: %d", i); + lcd_puts(0, line++, buf); + lcd_update(); + } + + disk_init(); + rc = disk_mount_all(); + if (rc<=0) { + lcd_puts(0, line++, "No partition found"); + lcd_update(); } - for(i = 0; i < (0xfffff); i++) + + pinfo = disk_partinfo(0); + snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB", + pinfo->type, pinfo->size / 2048); + lcd_puts(0, line++, buf); + lcd_update(); + + i=button_read_device(); + if(i==BUTTON_LEFT) { + lcd_puts(0, line, "Loading Sandisk firmware..."); + lcd_update(); + rc=load_sandisk(loadbuffer); + /* Sandisk firmware doesn't like having the cache enabled */ + } else { + lcd_puts(0, line, "Loading Rockbox..."); + lcd_update(); + rc=load_rockbox(loadbuffer); } - for(i = 0; i < (0xfffff); i++) - { + + if (rc < 0) { + snprintf(buf, sizeof(buf), "Rockbox error: %d",rc); + lcd_puts(0, line++, buf); + lcd_update(); + while(1) {} } -} -static inline unsigned long get_pc(void) -{ - unsigned long pc; - asm volatile ( - "mov %0, pc\n" - : "=r"(pc) - ); - return pc; + memcpy((void*)DRAM_START,loadbuffer,rc); + return (void*)DRAM_START; } /* These functions are present in the firmware library, but we reimplement @@ -100,62 +242,7 @@ int dbg_ports(void) { - unsigned int gpio_a, gpio_b, gpio_c, gpio_d; - unsigned int gpio_e, gpio_f, gpio_g, gpio_h; - unsigned int gpio_i, gpio_j, gpio_k, gpio_l; - - char buf[128]; - int line; - - lcd_setmargins(0, 0); - lcd_clear_display(); - lcd_setfont(FONT_SYSFIXED); - - while(1) - { - gpio_a = GPIOA_INPUT_VAL; - gpio_b = GPIOB_INPUT_VAL; - gpio_c = GPIOC_INPUT_VAL; - - gpio_g = GPIOG_INPUT_VAL; - gpio_h = GPIOH_INPUT_VAL; - gpio_i = GPIOI_INPUT_VAL; - - line = 0; - snprintf(buf, sizeof(buf), "GPIO_A: %02x GPIO_G: %02x", gpio_a, gpio_g); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "GPIO_B: %02x GPIO_H: %02x", gpio_b, gpio_h); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "GPIO_C: %02x GPIO_I: %02x", gpio_c, gpio_i); - lcd_puts(0, line++, buf); - line++; - - gpio_d = GPIOD_INPUT_VAL; - gpio_e = GPIOE_INPUT_VAL; - gpio_f = GPIOF_INPUT_VAL; - - gpio_j = GPIOJ_INPUT_VAL; - gpio_k = GPIOK_INPUT_VAL; - gpio_l = GPIOL_INPUT_VAL; - - snprintf(buf, sizeof(buf), "GPIO_D: %02x GPIO_J: %02x", gpio_d, gpio_j); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "GPIO_E: %02x GPIO_K: %02x", gpio_e, gpio_k); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "GPIO_F: %02x GPIO_L: %02x", gpio_f, gpio_l); - lcd_puts(0, line++, buf); - line++; - snprintf(buf, sizeof(buf), "ADC_1: %02x", adc_read(ADC_0)); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "ADC_2: %02x", adc_read(ADC_1)); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "ADC_3: %02x", adc_read(ADC_2)); - lcd_puts(0, line++, buf); - snprintf(buf, sizeof(buf), "ADC_4: %02x", adc_read(ADC_3)); - lcd_puts(0, line++, buf); - lcd_update(); - } - return 0; + return 0; } void mpeg_stop(void) @@ -173,18 +260,3 @@ void sys_poweroff(void) { } - -void system_reboot(void) -{ - -} - -void main(void) -{ - kernel_init(); - adc_init(); - lcd_init_device(); - - dbg_ports(); -} - Index: firmware/export/config-e200.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/config-e200.h,v retrieving revision 1.4 diff -u -r1.4 config-e200.h --- firmware/export/config-e200.h 22 Nov 2006 00:49:15 -0000 1.4 +++ firmware/export/config-e200.h 5 Dec 2006 01:27:24 -0000 @@ -4,7 +4,7 @@ #define TARGET_TREE /* this target is using the target tree system */ /* For Rolo and boot loader */ -#define MODEL_NUMBER 12 +#define MODEL_NUMBER 16 /* define this if you have recording possibility */ /*#define HAVE_RECORDING 1*/ /* TODO: add support for this */ Index: firmware/target/arm/crt0-pp.S =================================================================== RCS file: /cvsroot/rockbox/firmware/target/arm/crt0-pp.S,v retrieving revision 1.2 diff -u -r1.2 crt0-pp.S --- firmware/target/arm/crt0-pp.S 22 Nov 2006 00:49:16 -0000 1.2 +++ firmware/target/arm/crt0-pp.S 5 Dec 2006 01:27:24 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: crt0-pp.S,v 1.2 2006-11-22 00:49:16 dan_a Exp $ + * $Id: crt0-pp.S,v 1.2 2006/11/22 00:49:16 dan_a Exp $ * * Copyright (C) 2002 by Linus Nielsen Feltzing * @@ -52,17 +52,36 @@ msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ */ -#ifndef BOOTLOADER b pad_skip -#if defined(SANSA_E200) -/* mi4tool writes junk between 0xe0 and 0xeb. Avoid this. */ -.space 60*4 /* (more than enough) space for exception vectors */ -#else -.space 50*4 -#endif +.space 60*4 /* For bootloader builds on targets with mi4 firmware, scramble + writes data to 0xe0-0xeb, so jump past that. For normal builds + this provides more than enough space for exception vectors */ pad_skip: + +#ifdef BOOTLOADER +/* 1 - Copy the bootloader to IRAM */ + /* get the high part of our execute address */ + and r4, pc, #0xff000000 + + /* Copy bootloader to safe area - 0x40000000 */ + mov r5, #0x40000000 + ldr r6, = _dataend + sub r0, r6, r5 /* length of loader */ + add r8, r4, r0 /* r8 points to start of loader */ +1: + cmp r5, r6 + ldrcc r2, [r4], #4 + strcc r2, [r5], #4 + bcc 1b + +/* 2 - Jump both CPU and COP there */ + ldr pc, =start_loc /* jump to the relocated start_loc: */ + +start_loc: + +#else /* BOOTLOADER */ #ifdef SANSA_E200 /* On the Sansa, copying the vectors fails if the cache is initialised */ ldr r1, =CACHE_CTRL @@ -106,24 +125,63 @@ L_post_remap: .word remap_end remap_end: - /* After doing the remapping, send the COP to sleep. - On wakeup it will go to cop_init */ +#endif + + /* Send the COP to sleep. On wakeup it will go to cop_init */ ldr r0, =PROC_ID ldr r0, [r0] and r0, r0, #0xff cmp r0, #0x55 - beq 1f + beq cpu /* put us (co-processor) to sleep */ ldr r4, =COP_CTRL mov r3, #SLEEP str r3, [r4] + ldr pc, =cop_wake_start - ldr pc, =cop_init +cop_wake_start: + /* COP: Invalidate cache */ + ldr r0, =0xf000f044 + ldr r1, [r0] + orr r1, r1, #0x6 + str r1, [r0] + ldr r0, =0x6000c000 1: + ldr r1, [r0] + tst r1, #0x8000 + bne 1b + +#ifdef BOOTLOADER + ldr r0, =startup_loc + ldr pc, [r0] +#else + /* Setup stack for COP */ + ldr sp, =cop_stackend + mov r3, sp + ldr r2, =cop_stackbegin + ldr r4, =0xdeadbeef +2: + cmp r3, r2 + strhi r4, [r2], #4 + bhi 2b -#ifndef DEBUG + ldr sp, =cop_stackend + + /* Run cop_main() in apps/main.c */ + bl cop_main +#endif + +cpu: + /* Wait for COP to be sleeping */ + ldr r4, =COP_STATUS +1: + ldr r3, [r4] + ands r3, r3, #SLEEPING + beq 1b + +#ifndef BOOTLOADER /* Copy exception handler code to address 0 */ ldr r2, =_vectorsstart ldr r3, =_vectorsend @@ -133,24 +191,18 @@ ldrhi r5, [r4], #4 strhi r5, [r2], #4 bhi 1b -#else - ldr r1, =vectors - ldr r0, =irq_handler - str r0, [r1, #24] - ldr r0, =fiq_handler - str r0, [r1, #28] #endif -#ifndef STUB - /* Zero out IBSS */ - ldr r2, =_iedata - ldr r3, =_iend + /* Initialise bss section to zero */ + ldr r2, =_edata + ldr r3, =_end mov r4, #0 1: cmp r3, r2 strhi r4, [r2], #4 bhi 1b - + +#ifndef BOOTLOADER /* Copy the IRAM */ ldr r2, =_iramcopy ldr r3, =_iramstart @@ -160,18 +212,8 @@ ldrhi r5, [r2], #4 strhi r5, [r3], #4 bhi 1b -#endif /* !STUB */ -#endif /* !BOOTLOADER */ +#endif - /* Initialise bss section to zero */ - ldr r2, =_edata - ldr r3, =_end - mov r4, #0 -1: - cmp r3, r2 - strhi r4, [r2], #4 - bhi 1b - /* Set up some stack and munge it with 0xdeadbeef */ ldr sp, =stackend mov r3, sp @@ -183,76 +225,31 @@ bhi 1b #ifdef BOOTLOADER - /* TODO: the high part of the address is probably dependent on CONFIG_CPU. - Since we tend to use ifdefs for each chipset target - anyway, we might as well just hardcode it here. - */ - - /* get the high part of our execute address */ - ldr r0, =0xff000000 - and r8, pc, r0 @ r8 is used later - - /* Find out which processor we are */ - mov r0, #PROC_ID - ldr r0, [r0] - and r0, r0, #0xff - cmp r0, #0x55 - beq 1f - - /* put us (co-processor) to sleep */ - ldr r4, =COP_CTRL - mov r3, #SLEEP - str r3, [r4] - ldr pc, =cop_wake_start - -cop_wake_start: - /* jump the COP to startup */ - ldr r0, =startup_loc - ldr pc, [r0] - -1: - - /* get the high part of our execute address */ - ldr r2, =0xffffff00 - and r4, pc, r2 - - /* Copy bootloader to safe area - 0x40000000 */ - mov r5, #0x40000000 - ldr r6, = _dataend - sub r0, r6, r5 /* length of loader */ - add r0, r4, r0 /* r0 points to start of loader */ -1: - cmp r5, r6 - ldrcc r2, [r4], #4 - strcc r2, [r5], #4 - bcc 1b - - ldr pc, =start_loc /* jump to the relocated start_loc: */ - -start_loc: + mov r0, r8 /* r8 holds the start of the loader - copy this to r0 */ /* execute the loader - this will load an image to 0x10000000 */ bl main - /* Wake up the coprocessor before executing the firmware */ - - /* save the startup address for the COP */ ldr r1, =startup_loc str r0, [r1] - /* make sure COP is sleeping */ - ldr r4, =COP_STATUS + /* Flush cache */ + ldr r3, =0xf000f044 + ldr r4, [r3] + orr r4, r4, #0x2 + str r4, [r3] + + ldr r3, =0x6000c000 1: - ldr r3, [r4] - ands r3, r3, #SLEEPING - beq 1b + ldr r4, [r3] + tst r4, #0x8000 + bne 1b - /* wake up COP */ + /* Wake up the coprocessor before executing the firmware */ ldr r4, =COP_CTRL mov r3, #WAKE str r3, [r4] - /* jump to start location */ mov pc, r0 startup_loc: @@ -265,7 +262,7 @@ .space 400 #else /* BOOTLOADER */ - + /* Set up stack for IRQ mode */ msr cpsr_c, #0xd2 ldr sp, =irq_stack @@ -288,19 +285,6 @@ ldr sp, =stackend bl main /* main() should never return */ - -cop_init: - ldr sp, =cop_stackend - mov r3, sp - ldr r2, =cop_stackbegin - ldr r4, =0xdeadbeef -2: - cmp r3, r2 - strhi r4, [r2], #4 - bhi 2b - - ldr sp, =cop_stackend - bl cop_main /* Exception handlers. Will be copied to address 0 after memory remapping */ .section .vectors,"aw" @@ -385,5 +369,4 @@ /* 256 words of FIQ stack */ .space 256*4 fiq_stack: - -#endif /* BOOTLOADER */ +#endif /* BOOTLOADER */ Index: tools/configure =================================================================== RCS file: /cvsroot/rockbox/tools/configure,v retrieving revision 1.245 diff -u -r1.245 configure --- tools/configure 27 Nov 2006 02:15:39 -0000 1.245 +++ tools/configure 5 Dec 2006 01:27:27 -0000 @@ -1115,10 +1115,10 @@ target="-DSANSA_E200" memory=32 # supposedly arm7tdmicc - tool="$rootdir/tools/scramble -mi4v3" + tool="$rootdir/tools/scramble -add=e200" bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" bmp2rb_native="$rootdir/tools/bmp2rb -f 4" - output="PP5022.mi4" + output="rockbox.e200" appextra="recorder:gui" archosrom="" flash="" Index: tools/scramble.c =================================================================== RCS file: /cvsroot/rockbox/tools/scramble.c,v retrieving revision 1.35 diff -u -r1.35 scramble.c --- tools/scramble.c 31 Aug 2006 19:19:35 -0000 1.35 +++ tools/scramble.c 5 Dec 2006 01:27:28 -0000 @@ -89,7 +89,7 @@ "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n" "\t-add=X Rockbox generic \"add-up\" checksum format\n" "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd\n" - "\t ip3g, ip4g, mini, x5, h10, h10_5gb)\n" + "\t ip3g, ip4g, mini, x5, h10, h10_5gb, tpj2, e200)\n" "\nNo option results in Archos standard player/recorder format.\n"); exit(1); @@ -207,6 +207,8 @@ modelnum = 14; else if(!strcmp(&argv[1][5], "tpj2")) modelnum = 15; + else if(!strcmp(&argv[1][5], "e200")) + modelnum = 16; else { fprintf(stderr, "unsupported model: %s\n", &argv[1][5]); return 2;