| /* 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/kexec.h> | |
| .align 3 /* not needed for this code, but keeps fncpy() happy */ | |
| ENTRY(relocate_new_kernel) | |
| ldr r0,kexec_indirection_page | |
| ldr r1,kexec_start_address | |
| /* | |
| * 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,0 | |
| beq 1f | |
| bic r4,r3,#1 | |
| b 0b | |
| 1: | |
| /* Is it an indirection page */ | |
| tst r3,#2,0 | |
| beq 1f | |
| bic r0,r3,#2 | |
| b 0b | |
| 1: | |
| /* are we done ? */ | |
| tst r3,#4,0 | |
| beq 1f | |
| b 2f | |
| 1: | |
| /* is it source ? */ | |
| tst r3,#8,0 | |
| 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,kexec_mach_type | |
| ldr r2,kexec_boot_atags | |
| ARM( ret lr ) | |
| THUMB( bx lr ) | |
| .align | |
| .globl kexec_start_address | |
| kexec_start_address: | |
| .long 0x0 | |
| .globl kexec_indirection_page | |
| kexec_indirection_page: | |
| .long 0x0 | |
| .globl kexec_mach_type | |
| kexec_mach_type: | |
| .long 0x0 | |
| /* phy addr of the atags for the new kernel */ | |
| .globl kexec_boot_atags | |
| kexec_boot_atags: | |
| .long 0x0 | |
| ENDPROC(relocate_new_kernel) | |
| relocate_new_kernel_end: | |
| .globl relocate_new_kernel_size | |
| relocate_new_kernel_size: | |
| .long relocate_new_kernel_end - relocate_new_kernel | |