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