1/* 2 * (C) Copyright 2011-2012 3 * Pali Rohár <pali.rohar@gmail.com> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24#include <config.h> 25 26relocaddr: /* address of this relocaddr section after coping */ 27 .word . /* address of section (calculated at compile time) */ 28 29startaddr: /* address of u-boot after copying */ 30 .word CONFIG_SYS_TEXT_BASE 31 32kernaddr: /* address of kernel after copying */ 33 .word KERNEL_ADDRESS 34 35kernsize: /* maximal size of kernel image */ 36 .word KERNEL_MAXSIZE 37 38kernoffs: /* offset of kernel image in loaded u-boot */ 39 .word KERNEL_OFFSET 40 41imagesize: /* maximal size of image */ 42 .word IMAGE_MAXSIZE 43 44ih_magic: /* IH_MAGIC in big endian from include/image.h */ 45 .word 0x56190527 46 47/* 48 * Routine: save_boot_params (called after reset from start.S) 49 * Description: Copy attached kernel to address KERNEL_ADDRESS 50 * Copy u-boot to address CONFIG_SYS_TEXT_BASE 51 * Return to copied u-boot address 52 */ 53 54.global save_boot_params 55save_boot_params: 56 57 58/* Copy valid attached kernel to address KERNEL_ADDRESS */ 59 60copy_kernel_start: 61 adr r0, relocaddr /* r0 - address of section relocaddr */ 62 ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ 63 cmp r0, r1 64 65 /* r4 - calculated offset */ 66 subhi r4, r0, r1 67 sublo r4, r1, r0 68 69 /* r0 - start of kernel before */ 70 ldr r0, startaddr 71 addhi r0, r0, r4 72 sublo r0, r0, r4 73 ldr r1, kernoffs 74 add r0, r0, r1 75 76 /* r3 - start of kernel after */ 77 ldr r3, kernaddr 78 79 /* r2 - end of kernel after */ 80 ldr r1, kernsize 81 add r2, r3, r1 82 83 /* r1 - end of kernel before */ 84 add r1, r0, r1 85 86 /* remove header in target kernel */ 87 mov r5, #0 88 str r5, [r3] 89 90 /* check for valid kernel uImage */ 91 ldr r4, [r0] /* r4 - 4 bytes header of kernel */ 92 ldr r5, ih_magic /* r5 - IH_MAGIC */ 93 cmp r4, r5 94 bne copy_kernel_end /* skip if invalid image */ 95 96copy_kernel_loop: 97 ldmdb r1!, {r3 - r10} 98 stmdb r2!, {r3 - r10} 99 cmp r1, r0 100 bhi copy_kernel_loop 101 102copy_kernel_end: 103 mov r5, #0 104 str r5, [r0] /* remove 4 bytes header of kernel */ 105 106 107/* Fix u-boot code */ 108 109fix_start: 110 adr r0, relocaddr /* r0 - address of section relocaddr */ 111 ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ 112 cmp r0, r1 113 114 beq copy_uboot_end /* skip if u-boot is on correct address */ 115 116 /* r5 - calculated offset */ 117 subhi r5, r0, r1 118 sublo r5, r1, r0 119 120 /* r6 - maximal u-boot size */ 121 ldr r6, imagesize 122 123 /* fix return address */ 124 subhi lr, lr, r5 125 addlo lr, lr, r5 126 127 /* r1 - start of u-boot after */ 128 ldr r1, startaddr 129 130 /* r0 - start of u-boot before */ 131 addhi r0, r1, r5 132 sublo r0, r1, r5 133 134 /* check if we need to move uboot copy code before calling it */ 135 cmp r5, r6 136 bhi copy_uboot_start /* now coping u-boot code directly is safe */ 137 138 139copy_code_start: 140 /* r0 - start of u-boot before */ 141 /* r1 - start of u-boot after */ 142 /* r6 - maximal u-boot size */ 143 144 /* r7 - maximal kernel size */ 145 ldr r7, kernsize 146 147 /* r4 - end of kernel before */ 148 add r4, r0, r6 149 add r4, r4, r7 150 151 /* r5 - end of u-boot after */ 152 ldr r5, startaddr 153 add r5, r5, r6 154 155 /* r2 - start of loop code after */ 156 cmp r4, r5 /* higher address (r4 or r5) */ 157 movhs r2, r4 158 movlo r2, r5 159 160 /* r3 - end of loop code before */ 161 adr r3, end 162 163 /* r4 - end of loop code after */ 164 adr r4, copy_uboot_start 165 sub r4, r3, r4 166 add r4, r2, r4 167 168copy_code_loop: 169 ldmdb r3!, {r7 - r10} 170 stmdb r4!, {r7 - r10} 171 cmp r4, r2 172 bhi copy_code_loop 173 174copy_code_end: 175 mov pc, r2 176 177 178/* Copy u-boot to address CONFIG_SYS_TEXT_BASE */ 179 180copy_uboot_start: 181 /* r0 - start of u-boot before */ 182 /* r1 - start of u-boot after */ 183 /* r6 - maximal u-boot size */ 184 185 /* r2 - end of u-boot after */ 186 add r2, r1, r6 187 188 /* condition for copying from left to right */ 189 cmp r0, r1 190 addlo r1, r0, r6 /* r1 - end of u-boot before */ 191 blo copy_uboot_loop_right 192 193copy_uboot_loop_left: 194 ldmia r0!, {r3 - r10} 195 stmia r1!, {r3 - r10} 196 cmp r1, r2 197 blo copy_uboot_loop_left 198 b copy_uboot_end 199 200copy_uboot_loop_right: 201 ldmdb r1!, {r3 - r10} 202 stmdb r2!, {r3 - r10} 203 cmp r1, r0 204 bhi copy_uboot_loop_right 205 206copy_uboot_end: 207 bx lr 208 209end: 210