summaryrefslogtreecommitdiffstats
path: root/bootloader
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2012-04-27 16:19:31 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2012-04-27 16:19:42 +0200
commit79a667d3e247f0bf0fdbfb96b57f45d0403ca21c (patch)
treeafb19080cc5f10adf647c1732fc9998f90675b4e /bootloader
parent2bafdae6b1a92740df32bcc0830ed5235a3b6772 (diff)
downloadrockbox-79a667d3e247f0bf0fdbfb96b57f45d0403ca21c.tar.gz
rockbox-79a667d3e247f0bf0fdbfb96b57f45d0403ca21c.tar.bz2
rockbox-79a667d3e247f0bf0fdbfb96b57f45d0403ca21c.zip
rk27xx: Add failsafe mode to the bootloader
Change-Id: Iba8fdc50b3c71831a6f55d15779fee8d1f12cb4f
Diffstat (limited to 'bootloader')
-rw-r--r--bootloader/rk27xx.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/bootloader/rk27xx.c b/bootloader/rk27xx.c
index dfba9704c2..4afefebd2d 100644
--- a/bootloader/rk27xx.c
+++ b/bootloader/rk27xx.c
@@ -19,11 +19,59 @@
#include "crc32-rkw.h"
#include "rkw-loader.h"
+/* beginning of DRAM */
#define DRAM_ORIG 0x60000000
+
+/* bootloader code runs from 0x60700000
+ * so we cannot load more code to not overwrite ourself
+ */
#define LOAD_SIZE 0x700000
extern void show_logo( void );
+/* This function setup bare minimum
+ * and jumps to rom in order to activate
+ * hardcoded rkusb mode
+ */
+static void enter_rkusb(void)
+{
+ asm volatile (
+ /* turn off cache */
+ "ldr r0, =0xefff0000 \n"
+ "ldrh r1, [r0] \n"
+ "strh r1, [r0] \n"
+
+ /* turn off interrupts */
+ "mrs r0, cpsr \n"
+ "bic r0, r0, #0x1f \n"
+ "orr r0, r0, #0xd3 \n"
+ "msr cpsr, r0 \n"
+
+ /* disable iram remap */
+ "mov r0, #0x18000000 \n"
+ "add r0, r0, #0x1c000 \n"
+ "mov r1, #0 \n"
+ "str r1, [r0, #4] \n"
+
+ /* setup stacks in unmapped
+ * iram just as rom will do
+ */
+ "msr cpsr, #0xd2 \n"
+ "ldr r1, =0x18200274 \n"
+ "add r1, r1, #0x200 \n"
+ "mov sp, r1 \n"
+ "msr cpsr, #0xd3 \n"
+ "add r1, r1, #0x400 \n"
+ "mov sp, r1 \n"
+
+ /* jump to main() in rom
+ * just before dfu handler
+ */
+ "ldr r0, =0xec0 \n"
+ "bx r0 \n"
+ );
+}
+
void main(void) NORETURN_ATTR;
void main(void)
{
@@ -87,23 +135,53 @@ void main(void)
printf(rkw_strerror(ret));
lcd_update();
sleep(5*HZ);
- power_off();
+
+ /* if we boot rockbox we shutdown on error
+ * if we boot OF we fall back to rkusb mode on error
+ */
+ if (boot == rb)
+ {
+ power_off();
+ }
+ else
+ {
+ /* give visual feedback what we are doing */
+ printf("Entering rockchip USB mode...");
+ lcd_update();
+
+ enter_rkusb();
+ }
}
else
{
+ /* print 'Loading OK' */
printf(rkw_strerror(0));
sleep(HZ);
}
+ /* jump to entrypoint */
kernel_entry = (void*) loadbuffer;
commit_discard_idcache();
printf("Executing");
kernel_entry();
+ /* this should never be reached actually */
printf("ERR: Failed to boot");
sleep(5*HZ);
- power_off();
+
+ if (boot == rb)
+ {
+ power_off();
+ }
+ else
+ {
+ /* give visual feedback what we are doing */
+ printf("Entering rockchip USB mode...");
+ lcd_update();
+
+ enter_rkusb();
+ }
/* hang */
while(1);