hc
2024-08-12 233ab1bd4c5697f5cdec94e60206e8c6ac609b4c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
 * (C) Copyright 2011-2012
 * Pali Rohár <pali.rohar@gmail.com>
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#include <config.h>
 
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:
   /* Get return address */
   ldr    lr, =save_boot_params_ret
 
/* 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
 
   /* 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: