diff options
Diffstat (limited to 'arch/arm/kernel/relocate_kernel.S')
-rw-r--r-- | arch/arm/kernel/relocate_kernel.S | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S new file mode 100644 index 000000000..218d52436 --- /dev/null +++ b/arch/arm/kernel/relocate_kernel.S @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * relocate_kernel.S - put the kernel image in place to boot + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/asm-offsets.h> +#include <asm/kexec.h> + + .align 3 /* not needed for this code, but keeps fncpy() happy */ + +ENTRY(relocate_new_kernel) + + adr r7, relocate_new_kernel_end + ldr r0, [r7, #KEXEC_INDIR_PAGE] + ldr r1, [r7, #KEXEC_START_ADDR] + + /* + * If there is no indirection page (we are doing crashdumps) + * skip any relocation. + */ + cmp r0, #0 + beq 2f + +0: /* top, read another word for the indirection page */ + ldr r3, [r0],#4 + + /* Is it a destination page. Put destination address to r4 */ + tst r3,#1 + beq 1f + bic r4,r3,#1 + b 0b +1: + /* Is it an indirection page */ + tst r3,#2 + beq 1f + bic r0,r3,#2 + b 0b +1: + + /* are we done ? */ + tst r3,#4 + beq 1f + b 2f + +1: + /* is it source ? */ + tst r3,#8 + beq 0b + bic r3,r3,#8 + mov r6,#1024 +9: + ldr r5,[r3],#4 + str r5,[r4],#4 + subs r6,r6,#1 + bne 9b + b 0b + +2: + /* Jump to relocated kernel */ + mov lr, r1 + mov r0, #0 + ldr r1, [r7, #KEXEC_MACH_TYPE] + ldr r2, [r7, #KEXEC_R2] + ARM( ret lr ) + THUMB( bx lr ) + +ENDPROC(relocate_new_kernel) + + .align 3 +relocate_new_kernel_end: + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long relocate_new_kernel_end - relocate_new_kernel + + |