From b04a7a86e1d903a37091486764d0dfe09372d663 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sun, 11 Oct 2009 01:37:12 +0000 Subject: Make the Nano2G bootloader actually function as a bootloader. The resulting bootloader-ipodnano2g.ipod file needs to be encrypted on a target using the crypt_firmware plugin to create bootloader-ipodnano2g.ipodx, which can then be written to the firmware partition using the ipodpatcher patch at FS#10609. Dual-booting doesn't work yet - only Rockbox can be run. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23084 a1c6a512-1295-4272-9138-f99709370657 --- bootloader/SOURCES | 7 +- bootloader/ipodnano2g.c | 137 ++++++++++++++++----- firmware/target/arm/s5l8700/boot.lds | 12 +- firmware/target/arm/s5l8700/crt0.S | 21 +++- .../target/arm/s5l8700/ipodnano2g/ftl-target.h | 5 + tools/configure | 3 +- 6 files changed, 141 insertions(+), 44 deletions(-) diff --git a/bootloader/SOURCES b/bootloader/SOURCES index f297f18fba..a512064ffd 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -1,6 +1,8 @@ common.c -#if defined(IPOD_ARCH) +#if defined(IPOD_NANO2G) +ipodnano2g.c +#elif defined(IPOD_ARCH) ipod.c #elif defined(GIGABEAT_F) gigabeat.c @@ -55,7 +57,4 @@ show_logo.c #elif defined(LYRE_PROTO1) lyre_proto1.c show_logo.c -#elif defined(IPOD_NANO2G) -ipodnano2g.c -show_logo.c #endif diff --git a/bootloader/ipodnano2g.c b/bootloader/ipodnano2g.c index f6bfe148ac..f05829eb6d 100644 --- a/bootloader/ipodnano2g.c +++ b/bootloader/ipodnano2g.c @@ -45,56 +45,127 @@ #include "file.h" #include "common.h" -char version[] = APPSVERSION; +/* Safety measure - maximum allowed firmware image size. + The largest known current (October 2009) firmware is about 6.2MB so + we set this to 8MB. +*/ +#define MAX_LOADSIZE (8*1024*1024) + +/* The buffer to load the firmware into */ +unsigned char *loadbuffer = (unsigned char *)0x08000000; -/* Show the Rockbox logo - in show_logo.c */ -extern int show_logo(void); +/* Bootloader version */ +char version[] = APPSVERSION; extern int line; +void fatal_error(void) +{ + extern int line; + bool holdstatus=false; + + /* System font is 6 pixels wide */ + printf("Hold MENU+SELECT to"); + printf("reboot then SELECT+PLAY"); + printf("for disk mode"); + lcd_update(); + + while (1) { + if (button_hold() != holdstatus) { + if (button_hold()) { + holdstatus=true; + lcd_puts(0, line, "Hold switch on!"); + } else { + holdstatus=false; + lcd_puts(0, line, " "); + } + lcd_update(); + } + } +} + void main(void) { int i; + int btn; + int rc; + bool button_was_held; + + /* Check the button hold status as soon as possible - to + give the user maximum chance to turn it on in order to + reset the settings in rockbox. */ + button_was_held = button_hold(); system_init(); - i2c_init(); kernel_init(); + i2c_init(); + enable_irq(); + backlight_init(); /* Turns on the backlight */ + lcd_init(); + font_init(); + + lcd_set_foreground(LCD_WHITE); + lcd_set_background(LCD_BLACK); + lcd_clear_display(); + +// button_init(); + + btn=0; /* TODO */ - _backlight_init(); - - lcd_puts_scroll(0,0,"+++ this is a very very long line to test scrolling. ---"); - verbose = 0; - i = 0; - while (!button_hold()) { - line = 1; - - printf("i=%d",i++); - printf("TBCNT: %08x",TBCNT); - printf("GPIO 0: %08x",PDAT0); - printf("GPIO 1: %08x",PDAT1); - printf("GPIO 2: %08x",PDAT2); - printf("GPIO 3: %08x",PDAT3); - printf("GPIO 4: %08x",PDAT4); - printf("GPIO 5: %08x",PDAT5); - printf("GPIO 6: %08x",PDAT6); - printf("GPIO 7: %08x",PDAT7); - printf("GPIO 10: %08x",PDAT10); - printf("GPIO 11: %08x",PDAT11); - printf("GPIO 13: %08x",PDAT13); - printf("GPIO 14: %08x",PDAT14); - - lcd_update(); + /* Enable bootloader messages */ + if (btn==BUTTON_RIGHT) + verbose = true; + + lcd_setfont(FONT_SYSFIXED); + + printf("Rockbox boot loader"); + printf("Version: %s", version); + + i = storage_init(); + + if (i != 0) { + printf("ATA error: %d", i); + fatal_error(); } - disable_irq(); + disk_init(); + rc = disk_mount_all(); + if (rc<=0) + { + printf("No partition found"); + fatal_error(); + } + + if (button_was_held || (btn==BUTTON_MENU)) { + /* If either the hold switch was on, or the Menu button was held, then + try the Apple firmware */ - /* Branch back to iBugger entry point */ - asm volatile("ldr pc, =0x08640568"); + printf("Loading original firmware..."); + + /* TODO */ + fatal_error(); + } else { + printf("Loading Rockbox..."); + rc=load_firmware(loadbuffer, BOOTFILE, MAX_LOADSIZE); + + if (rc != EOK) { + printf("Error!"); + printf("Can't load " BOOTFILE ": "); + printf(strerror(rc)); + fatal_error(); + } + + printf("Rockbox loaded."); + } + + /* If we get here, we have a new firmware image at 0x08000000, run it */ + + disable_irq(); - /* We never reach here */ - while(1); + /* Branch to start of DRAM */ + asm volatile("ldr pc, =0x08000000"); } diff --git a/firmware/target/arm/s5l8700/boot.lds b/firmware/target/arm/s5l8700/boot.lds index 2dea0ee4ea..637a3a29c1 100644 --- a/firmware/target/arm/s5l8700/boot.lds +++ b/firmware/target/arm/s5l8700/boot.lds @@ -9,14 +9,14 @@ OUTPUT_FORMAT(elf32-bigarm) OUTPUT_ARCH(arm) STARTUP(target/arm/s5l8700/crt0.o) -/* DRAMORIG is in fact 0x08000000 but remapped to 0x0 */ #define DRAMORIG 0x08000000 #define DRAMSIZE (MEMORYSIZE * 0x100000) -#define IRAMORIG 0x22000000 #if CONFIG_CPU==S5L8701 +#define IRAMORIG 0x0 #define IRAMSIZE 176K #else +#define IRAMORIG 0x22000000 #define IRAMSIZE 256K #endif @@ -91,7 +91,11 @@ SECTIONS _fiqstackend = .; } > IRAM - .bss : { + /* The bss section is too large for IRAM - we just move it 12MB into the + DRAM */ + + . = DRAMORIG; + .bss . + (12*1024*1024): { _edata = .; *(.bss*); *(.ibss); @@ -99,5 +103,5 @@ SECTIONS *(COMMON); . = ALIGN(0x4); _end = .; - } > IRAM + } > DRAM } diff --git a/firmware/target/arm/s5l8700/crt0.S b/firmware/target/arm/s5l8700/crt0.S index 4a89f3da39..aa2923cb29 100644 --- a/firmware/target/arm/s5l8700/crt0.S +++ b/firmware/target/arm/s5l8700/crt0.S @@ -27,7 +27,11 @@ .global _newstart /* Exception vectors */ start: +#if CONFIG_CPU==S5L8701 && defined(BOOTLOADER) + b newstart2 +#else b _newstart +#endif ldr pc, =undef_instr_handler ldr pc, =software_int_handler ldr pc, =prefetch_abort_handler @@ -88,7 +92,22 @@ newstart2: orr r2, r2, #1 bic r2, r2, #0x10000 str r2, [r1] // remap iram to address 0x0 -#endif + +#ifdef BOOTLOADER + /* Relocate ourself to IRAM - we have been loaded to DRAM */ + mov r0, #0x08000000 /* source (DRAM) */ + mov r1, #0x00000000 /* dest (IRAM) */ + ldr r2, =_dataend +1: + cmp r2, r1 + ldrhi r3, [r0], #4 + strhi r3, [r1], #4 + bhi 1b + + ldr pc, =start_loc /* jump to the relocated start_loc: */ +start_loc: +#endif /* BOOTLOADER */ +#endif /* CONFIG_CPU==S5L8701 */ ldr r1, =0x3c500000 // CLKCON ldr r0, =0x00800080 diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-target.h b/firmware/target/arm/s5l8700/ipodnano2g/ftl-target.h index f214964551..0c36db9799 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-target.h +++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-target.h @@ -25,6 +25,11 @@ #include "config.h" #include "inttypes.h" +#ifdef BOOTLOADER +/* Bootloaders don't need write access */ +#define FTL_READONLY +#endif + uint32_t ftl_init(void); uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer); uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer); diff --git a/tools/configure b/tools/configure index acbfba42e0..790be27cc5 100755 --- a/tools/configure +++ b/tools/configure @@ -1441,8 +1441,7 @@ fi appextra="recorder:gui" plugins="yes" swcodec="yes" - boottool="cp" - bootoutput="bootloader-$modelname.bin" + bootoutput="bootloader-$modelname.ipod" # toolset is the tools within the tools directory that we build for # this particular target. toolset=$ipodbitmaptools -- cgit v1.2.3