]>
Commit | Line | Data |
---|---|---|
ed407be5 T |
1 | /* |
2 | * (C) Copyright 2011-2012 | |
3 | * Pali Rohár <[email protected]> | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
ed407be5 T |
6 | */ |
7 | ||
8 | #include <config.h> | |
9 | ||
10 | relocaddr: /* address of this relocaddr section after coping */ | |
11 | .word . /* address of section (calculated at compile time) */ | |
12 | ||
13 | startaddr: /* address of u-boot after copying */ | |
14 | .word CONFIG_SYS_TEXT_BASE | |
15 | ||
16 | kernaddr: /* address of kernel after copying */ | |
17 | .word KERNEL_ADDRESS | |
18 | ||
19 | kernsize: /* maximal size of kernel image */ | |
20 | .word KERNEL_MAXSIZE | |
21 | ||
22 | kernoffs: /* offset of kernel image in loaded u-boot */ | |
23 | .word KERNEL_OFFSET | |
24 | ||
25 | imagesize: /* maximal size of image */ | |
26 | .word IMAGE_MAXSIZE | |
27 | ||
28 | ih_magic: /* IH_MAGIC in big endian from include/image.h */ | |
29 | .word 0x56190527 | |
30 | ||
31 | /* | |
32 | * Routine: save_boot_params (called after reset from start.S) | |
33 | * Description: Copy attached kernel to address KERNEL_ADDRESS | |
34 | * Copy u-boot to address CONFIG_SYS_TEXT_BASE | |
35 | * Return to copied u-boot address | |
36 | */ | |
37 | ||
38 | .global save_boot_params | |
39 | save_boot_params: | |
40 | ||
41 | ||
42 | /* Copy valid attached kernel to address KERNEL_ADDRESS */ | |
43 | ||
44 | copy_kernel_start: | |
45 | adr r0, relocaddr /* r0 - address of section relocaddr */ | |
46 | ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ | |
47 | cmp r0, r1 | |
48 | ||
49 | /* r4 - calculated offset */ | |
50 | subhi r4, r0, r1 | |
51 | sublo r4, r1, r0 | |
52 | ||
53 | /* r0 - start of kernel before */ | |
54 | ldr r0, startaddr | |
55 | addhi r0, r0, r4 | |
56 | sublo r0, r0, r4 | |
57 | ldr r1, kernoffs | |
58 | add r0, r0, r1 | |
59 | ||
60 | /* r3 - start of kernel after */ | |
61 | ldr r3, kernaddr | |
62 | ||
63 | /* r2 - end of kernel after */ | |
64 | ldr r1, kernsize | |
65 | add r2, r3, r1 | |
66 | ||
67 | /* r1 - end of kernel before */ | |
68 | add r1, r0, r1 | |
69 | ||
70 | /* remove header in target kernel */ | |
71 | mov r5, #0 | |
72 | str r5, [r3] | |
73 | ||
74 | /* check for valid kernel uImage */ | |
75 | ldr r4, [r0] /* r4 - 4 bytes header of kernel */ | |
76 | ldr r5, ih_magic /* r5 - IH_MAGIC */ | |
77 | cmp r4, r5 | |
78 | bne copy_kernel_end /* skip if invalid image */ | |
79 | ||
80 | copy_kernel_loop: | |
81 | ldmdb r1!, {r3 - r10} | |
82 | stmdb r2!, {r3 - r10} | |
83 | cmp r1, r0 | |
84 | bhi copy_kernel_loop | |
85 | ||
86 | copy_kernel_end: | |
87 | mov r5, #0 | |
88 | str r5, [r0] /* remove 4 bytes header of kernel */ | |
89 | ||
90 | ||
91 | /* Fix u-boot code */ | |
92 | ||
93 | fix_start: | |
94 | adr r0, relocaddr /* r0 - address of section relocaddr */ | |
95 | ldr r1, relocaddr /* r1 - address of relocaddr after relocation */ | |
96 | cmp r0, r1 | |
97 | ||
98 | beq copy_uboot_end /* skip if u-boot is on correct address */ | |
99 | ||
100 | /* r5 - calculated offset */ | |
101 | subhi r5, r0, r1 | |
102 | sublo r5, r1, r0 | |
103 | ||
104 | /* r6 - maximal u-boot size */ | |
105 | ldr r6, imagesize | |
106 | ||
107 | /* fix return address */ | |
108 | subhi lr, lr, r5 | |
109 | addlo lr, lr, r5 | |
110 | ||
111 | /* r1 - start of u-boot after */ | |
112 | ldr r1, startaddr | |
113 | ||
114 | /* r0 - start of u-boot before */ | |
115 | addhi r0, r1, r5 | |
116 | sublo r0, r1, r5 | |
117 | ||
118 | /* check if we need to move uboot copy code before calling it */ | |
119 | cmp r5, r6 | |
120 | bhi copy_uboot_start /* now coping u-boot code directly is safe */ | |
121 | ||
122 | ||
123 | copy_code_start: | |
124 | /* r0 - start of u-boot before */ | |
125 | /* r1 - start of u-boot after */ | |
126 | /* r6 - maximal u-boot size */ | |
127 | ||
128 | /* r7 - maximal kernel size */ | |
129 | ldr r7, kernsize | |
130 | ||
131 | /* r4 - end of kernel before */ | |
132 | add r4, r0, r6 | |
133 | add r4, r4, r7 | |
134 | ||
135 | /* r5 - end of u-boot after */ | |
136 | ldr r5, startaddr | |
137 | add r5, r5, r6 | |
138 | ||
139 | /* r2 - start of loop code after */ | |
140 | cmp r4, r5 /* higher address (r4 or r5) */ | |
141 | movhs r2, r4 | |
142 | movlo r2, r5 | |
143 | ||
144 | /* r3 - end of loop code before */ | |
145 | adr r3, end | |
146 | ||
147 | /* r4 - end of loop code after */ | |
148 | adr r4, copy_uboot_start | |
149 | sub r4, r3, r4 | |
150 | add r4, r2, r4 | |
151 | ||
152 | copy_code_loop: | |
153 | ldmdb r3!, {r7 - r10} | |
154 | stmdb r4!, {r7 - r10} | |
155 | cmp r4, r2 | |
156 | bhi copy_code_loop | |
157 | ||
158 | copy_code_end: | |
159 | mov pc, r2 | |
160 | ||
161 | ||
162 | /* Copy u-boot to address CONFIG_SYS_TEXT_BASE */ | |
163 | ||
164 | copy_uboot_start: | |
165 | /* r0 - start of u-boot before */ | |
166 | /* r1 - start of u-boot after */ | |
167 | /* r6 - maximal u-boot size */ | |
168 | ||
169 | /* r2 - end of u-boot after */ | |
170 | add r2, r1, r6 | |
171 | ||
172 | /* condition for copying from left to right */ | |
173 | cmp r0, r1 | |
174 | addlo r1, r0, r6 /* r1 - end of u-boot before */ | |
175 | blo copy_uboot_loop_right | |
176 | ||
177 | copy_uboot_loop_left: | |
178 | ldmia r0!, {r3 - r10} | |
179 | stmia r1!, {r3 - r10} | |
180 | cmp r1, r2 | |
181 | blo copy_uboot_loop_left | |
182 | b copy_uboot_end | |
183 | ||
184 | copy_uboot_loop_right: | |
185 | ldmdb r1!, {r3 - r10} | |
186 | stmdb r2!, {r3 - r10} | |
187 | cmp r1, r0 | |
188 | bhi copy_uboot_loop_right | |
189 | ||
190 | copy_uboot_end: | |
191 | bx lr | |
192 | ||
193 | end: |