aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ramips/image/relocate/head.S
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2015-01-17 21:19:38 +0000
committerFelix Fietkau <nbd@openwrt.org>2015-01-17 21:19:38 +0000
commit506958b6f34cefa863ee3cee3656ef6cadbd6eb8 (patch)
tree9d0ed8708e6a7f2c388d06b4825bd05e1896558f /target/linux/ramips/image/relocate/head.S
parent3ef1fdbe0562d78a30ad27c33190fb4766d52b41 (diff)
downloadmaster-187ad058-506958b6f34cefa863ee3cee3656ef6cadbd6eb8.tar.gz
master-187ad058-506958b6f34cefa863ee3cee3656ef6cadbd6eb8.tar.bz2
master-187ad058-506958b6f34cefa863ee3cee3656ef6cadbd6eb8.zip
ramips: add code for relocating a kernel to the right place
(used if the boot loader wants a different loadaddr/entry) Signed-off-by: Felix Fietkau <nbd@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@44014 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ramips/image/relocate/head.S')
-rw-r--r--target/linux/ramips/image/relocate/head.S153
1 files changed, 153 insertions, 0 deletions
diff --git a/target/linux/ramips/image/relocate/head.S b/target/linux/ramips/image/relocate/head.S
new file mode 100644
index 0000000000..3680cb7d8d
--- /dev/null
+++ b/target/linux/ramips/image/relocate/head.S
@@ -0,0 +1,153 @@
+/*
+ * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Some parts of this code was based on the OpenWrt specific lzma-loader
+ * for the BCM47xx and ADM5120 based boards:
+ * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include "cp0regdef.h"
+#include "cacheops.h"
+
+#define KSEG0 0x80000000
+
+ .macro ehb
+ sll zero, 3
+ .endm
+
+ .macro reset
+ li t0, 0xbe000034
+ lw t1, 0(t0)
+ ori t1, 1
+ sw t1, 0(t0)
+ .endm
+
+ .text
+
+LEAF(startup)
+ .set noreorder
+ .set mips32
+
+ .fill 0x10000
+
+ mtc0 zero, CP0_WATCHLO # clear watch registers
+ mtc0 zero, CP0_WATCHHI
+ mtc0 zero, CP0_CAUSE # clear before writing status register
+
+ mfc0 t0, CP0_STATUS
+ li t1, 0x1000001f
+ or t0, t1
+ xori t0, 0x1f
+ mtc0 t0, CP0_STATUS
+ ehb
+
+ mtc0 zero, CP0_COUNT
+ mtc0 zero, CP0_COMPARE
+ ehb
+
+ la t0, __reloc_label # get linked address of label
+ bal __reloc_label # branch and link to label to
+ nop # get actual address
+__reloc_label:
+ subu t0, ra, t0 # get reloc_delta
+
+ /* Copy our code to the right place */
+ la t1, _code_start # get linked address of _code_start
+ la t2, _code_end # get linked address of _code_end
+
+ addu t4, t2, t0 # calculate actual address of _code_end
+ lw t5, 0(t4) # get extra data size
+
+ add t2, t5
+ add t2, 4
+
+ add t0, t1 # calculate actual address of _code_start
+
+__reloc_copy:
+ lw t3, 0(t0)
+ sw t3, 0(t1)
+ add t1, 4
+ blt t1, t2, __reloc_copy
+ add t0, 4
+
+ /* flush cache */
+ la t0, _code_start
+ la t1, _code_end
+
+ li t2, ~(CONFIG_CACHELINE_SIZE - 1)
+ and t0, t2
+ and t1, t2
+ li t2, CONFIG_CACHELINE_SIZE
+
+ b __flush_check
+ nop
+
+__flush_line:
+ cache Hit_Writeback_Inv_D, 0(t0)
+ cache Hit_Invalidate_I, 0(t0)
+ add t0, t2
+
+__flush_check:
+ bne t0, t1, __flush_line
+ nop
+
+ sync
+
+ la t0, __reloc_back
+ j t0
+ nop
+
+__reloc_back:
+ la t0, _code_end
+ add t0, 4
+
+ addu t1, t0, t5
+
+ li t2, KERNEL_ADDR
+
+__kernel_copy:
+ lw t3, 0(t0)
+ sw t3, 0(t2)
+ add t0, 4
+ blt t0, t1, __kernel_copy
+ add t2, 4
+
+ /* flush cache */
+ li t0, KERNEL_ADDR
+ addu t1, t0, t5
+
+ add t1, CONFIG_CACHELINE_SIZE - 1
+ li t2, ~(CONFIG_CACHELINE_SIZE - 1)
+ and t0, t2
+ and t1, t2
+ li t2, CONFIG_CACHELINE_SIZE
+
+ b __kernel_flush_check
+ nop
+
+__kernel_flush_line:
+ cache Hit_Writeback_Inv_D, 0(t0)
+ cache Hit_Invalidate_I, 0(t0)
+ add t0, t2
+
+__kernel_flush_check:
+ bne t0, t1, __kernel_flush_line
+ nop
+
+ sync
+
+ li t0, KERNEL_ADDR
+ jr t0
+ nop
+
+ .set reorder
+END(startup)