diff options
author | Felix Fietkau <nbd@openwrt.org> | 2015-01-17 21:19:38 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2015-01-17 21:19:38 +0000 |
commit | 506958b6f34cefa863ee3cee3656ef6cadbd6eb8 (patch) | |
tree | 9d0ed8708e6a7f2c388d06b4825bd05e1896558f /target/linux/ramips/image/relocate/head.S | |
parent | 3ef1fdbe0562d78a30ad27c33190fb4766d52b41 (diff) | |
download | master-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.S | 153 |
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) |