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	/* r1 - start of u-boot after */
109	ldr	r1, startaddr
110
111	/* r0 - start of u-boot before */
112	addhi	r0, r1, r5
113	sublo	r0, r1, r5
114
115	/* check if we need to move uboot copy code before calling it */
116	cmp	r5, r6
117	bhi	copy_uboot_start /* now coping u-boot code directly is safe */
118
119
120copy_code_start:
121	/* r0 - start of u-boot before */
122	/* r1 - start of u-boot after */
123	/* r6 - maximal u-boot size */
124
125	/* r7 - maximal kernel size */
126	ldr	r7, kernsize
127
128	/* r4 - end of kernel before */
129	add	r4, r0, r6
130	add	r4, r4, r7
131
132	/* r5 - end of u-boot after */
133	ldr	r5, startaddr
134	add	r5, r5, r6
135
136	/* r2 - start of loop code after */
137	cmp	r4, r5		/* higher address (r4 or r5) */
138	movhs	r2, r4
139	movlo	r2, r5
140
141	/* r3 - end of loop code before */
142	adr	r3, end
143
144	/* r4 - end of loop code after */
145	adr	r4, copy_uboot_start
146	sub	r4, r3, r4
147	add	r4, r2, r4
148
149copy_code_loop:
150	ldmdb	r3!, {r7 - r10}
151	stmdb	r4!, {r7 - r10}
152	cmp	r4, r2
153	bhi	copy_code_loop
154
155copy_code_end:
156	mov	pc, r2
157
158
159/* Copy u-boot to address CONFIG_SYS_TEXT_BASE */
160
161copy_uboot_start:
162	/* r0 - start of u-boot before */
163	/* r1 - start of u-boot after */
164	/* r6 - maximal u-boot size */
165
166	/* r2 - end of u-boot after */
167	add	r2, r1, r6
168
169	/* condition for copying from left to right */
170	cmp	r0, r1
171	addlo	r1, r0, r6	/* r1 - end of u-boot before */
172	blo	copy_uboot_loop_right
173
174copy_uboot_loop_left:
175	ldmia	r0!, {r3 - r10}
176	stmia	r1!, {r3 - r10}
177	cmp	r1, r2
178	blo	copy_uboot_loop_left
179	b	copy_uboot_end
180
181copy_uboot_loop_right:
182	ldmdb	r1!, {r3 - r10}
183	stmdb	r2!, {r3 - r10}
184	cmp	r1, r0
185	bhi	copy_uboot_loop_right
186
187copy_uboot_end:
188	bx	lr
189
190end:
191