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
41
42/* Copy valid attached kernel to address KERNEL_ADDRESS */
43
44copy_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
80copy_kernel_loop:
81	ldmdb	r1!, {r3 - r10}
82	stmdb	r2!, {r3 - r10}
83	cmp	r1, r0
84	bhi	copy_kernel_loop
85
86copy_kernel_end:
87	mov	r5, #0
88	str	r5, [r0]	/* remove 4 bytes header of kernel */
89
90
91/* Fix u-boot code */
92
93fix_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
123copy_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
152copy_code_loop:
153	ldmdb	r3!, {r7 - r10}
154	stmdb	r4!, {r7 - r10}
155	cmp	r4, r2
156	bhi	copy_code_loop
157
158copy_code_end:
159	mov	pc, r2
160
161
162/* Copy u-boot to address CONFIG_SYS_TEXT_BASE */
163
164copy_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
177copy_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
184copy_uboot_loop_right:
185	ldmdb	r1!, {r3 - r10}
186	stmdb	r2!, {r3 - r10}
187	cmp	r1, r0
188	bhi	copy_uboot_loop_right
189
190copy_uboot_end:
191	bx	lr
192
193end:
194