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