blob: 055b1038d142ac8141487638743e411e54c0dd5f [file] [log] [blame]
Pali Rohár248ef0a2012-10-29 07:54:01 +00001/*
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: