/* * (C) Copyright 2011-2012 * Pali Rohár * * SPDX-License-Identifier: GPL-2.0+ */ #include relocaddr: /* address of this relocaddr section after coping */ .word . /* address of section (calculated at compile time) */ startaddr: /* address of u-boot after copying */ .word CONFIG_SYS_TEXT_BASE kernaddr: /* address of kernel after copying */ .word KERNEL_ADDRESS kernsize: /* maximal size of kernel image */ .word KERNEL_MAXSIZE kernoffs: /* offset of kernel image in loaded u-boot */ .word KERNEL_OFFSET imagesize: /* maximal size of image */ .word IMAGE_MAXSIZE ih_magic: /* IH_MAGIC in big endian from include/image.h */ .word 0x56190527 /* * Routine: save_boot_params (called after reset from start.S) * Description: Copy attached kernel to address KERNEL_ADDRESS * Copy u-boot to address CONFIG_SYS_TEXT_BASE * Return to copied u-boot address */ .global save_boot_params save_boot_params: /* Copy valid attached kernel to address KERNEL_ADDRESS */ copy_kernel_start: adr r0, relocaddr /* r0 - address of section relocaddr */ ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ cmp r0, r1 /* r4 - calculated offset */ subhi r4, r0, r1 sublo r4, r1, r0 /* r0 - start of kernel before */ ldr r0, startaddr addhi r0, r0, r4 sublo r0, r0, r4 ldr r1, kernoffs add r0, r0, r1 /* r3 - start of kernel after */ ldr r3, kernaddr /* r2 - end of kernel after */ ldr r1, kernsize add r2, r3, r1 /* r1 - end of kernel before */ add r1, r0, r1 /* remove header in target kernel */ mov r5, #0 str r5, [r3] /* check for valid kernel uImage */ ldr r4, [r0] /* r4 - 4 bytes header of kernel */ ldr r5, ih_magic /* r5 - IH_MAGIC */ cmp r4, r5 bne copy_kernel_end /* skip if invalid image */ copy_kernel_loop: ldmdb r1!, {r3 - r10} stmdb r2!, {r3 - r10} cmp r1, r0 bhi copy_kernel_loop copy_kernel_end: mov r5, #0 str r5, [r0] /* remove 4 bytes header of kernel */ /* Fix u-boot code */ fix_start: adr r0, relocaddr /* r0 - address of section relocaddr */ ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ cmp r0, r1 beq copy_uboot_end /* skip if u-boot is on correct address */ /* r5 - calculated offset */ subhi r5, r0, r1 sublo r5, r1, r0 /* r6 - maximal u-boot size */ ldr r6, imagesize /* fix return address */ subhi lr, lr, r5 addlo lr, lr, r5 /* r1 - start of u-boot after */ ldr r1, startaddr /* r0 - start of u-boot before */ addhi r0, r1, r5 sublo r0, r1, r5 /* check if we need to move uboot copy code before calling it */ cmp r5, r6 bhi copy_uboot_start /* now coping u-boot code directly is safe */ copy_code_start: /* r0 - start of u-boot before */ /* r1 - start of u-boot after */ /* r6 - maximal u-boot size */ /* r7 - maximal kernel size */ ldr r7, kernsize /* r4 - end of kernel before */ add r4, r0, r6 add r4, r4, r7 /* r5 - end of u-boot after */ ldr r5, startaddr add r5, r5, r6 /* r2 - start of loop code after */ cmp r4, r5 /* higher address (r4 or r5) */ movhs r2, r4 movlo r2, r5 /* r3 - end of loop code before */ adr r3, end /* r4 - end of loop code after */ adr r4, copy_uboot_start sub r4, r3, r4 add r4, r2, r4 copy_code_loop: ldmdb r3!, {r7 - r10} stmdb r4!, {r7 - r10} cmp r4, r2 bhi copy_code_loop copy_code_end: mov pc, r2 /* Copy u-boot to address CONFIG_SYS_TEXT_BASE */ copy_uboot_start: /* r0 - start of u-boot before */ /* r1 - start of u-boot after */ /* r6 - maximal u-boot size */ /* r2 - end of u-boot after */ add r2, r1, r6 /* condition for copying from left to right */ cmp r0, r1 addlo r1, r0, r6 /* r1 - end of u-boot before */ blo copy_uboot_loop_right copy_uboot_loop_left: ldmia r0!, {r3 - r10} stmia r1!, {r3 - r10} cmp r1, r2 blo copy_uboot_loop_left b copy_uboot_end copy_uboot_loop_right: ldmdb r1!, {r3 - r10} stmdb r2!, {r3 - r10} cmp r1, r0 bhi copy_uboot_loop_right copy_uboot_end: bx lr end: