1/* SPDX-License-Identifier: GPL-2.0 */
2#include <variant/core.h>
3#include <asm/regs.h>
4#include <asm/asmmacro.h>
5#include <asm/cacheasm.h>
6	/*
7	 * RB-Data: RedBoot data/bss
8	 * P:	    Boot-Parameters
9	 * L:	    Kernel-Loader
10	 *
11	 * The Linux-Kernel image including the loader must be loaded
12	 * to a position so that the kernel and the boot parameters
13	 * can fit in the space before the load address.
14	 *  ______________________________________________________
15	 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
16	 *                          ^
17	 *                          ^ Load address
18	 *  ______________________________________________________
19	 * |___Linux-Kernel___|_P_|_L_|___________________________|
20	 *
21	 * The loader copies the parameter to the position that will
22	 * be the end of the kernel and itself to the end of the
23	 * parameter list.
24	 */
25
26/* Make sure we have enough space for the 'uncompressor' */
27
28#define STACK_SIZE 32768
29#define HEAP_SIZE (131072*4)
30
31	# a2: Parameter list
32	# a3: Size of parameter list
33
34	.section .start, "ax"
35
36	.globl __start
37	/* this must be the first byte of the loader! */
38__start:
39	entry	sp, 32		# we do not intend to return
40	_call0	_start
41__start_a0:
42	.align 4
43
44	.section .text, "ax"
45	.begin literal_prefix .text
46
47	/* put literals in here! */
48
49	.globl _start
50_start:
51
52	/* 'reset' window registers */
53
54	movi	a4, 1
55	wsr	a4, ps
56	rsync
57
58	rsr	a5, windowbase
59	ssl	a5
60	sll	a4, a4
61	wsr	a4, windowstart
62	rsync
63
64	movi	a4, 0x00040000
65	wsr	a4, ps
66	rsync
67
68	/* copy the loader to its address
69	 * Note: The loader itself is a very small piece, so we assume we
70	 *       don't partially overlap. We also assume (even more important)
71	 *	 that the kernel image is out of the way. Usually, when the
72	 *	 load address of this image is not at an arbitrary address,
73	 *	 but aligned to some 10K's we shouldn't overlap.
74	 */
75
76	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
77	   l32r, so we load to a4 first. */
78
79	# addi	a4, a0, __start - __start_a0
80	# mov	a0, a4
81
82	movi	a4, __start
83	movi	a5, __start_a0
84	add	a4, a0, a4
85	sub	a0, a4, a5
86
87	movi	a4, __start
88	movi	a5, __reloc_end
89
90	# a0: address where this code has been loaded
91	# a4: compiled address of __start
92	# a5: compiled end address
93
94	mov.n	a7, a0
95	mov.n	a8, a4
96
971:
98	l32i	a10, a7, 0
99	l32i	a11, a7, 4
100	s32i	a10, a8, 0
101	s32i	a11, a8, 4
102	l32i	a10, a7, 8
103	l32i	a11, a7, 12
104	s32i	a10, a8, 8
105	s32i	a11, a8, 12
106	addi	a8, a8, 16
107	addi	a7, a7, 16
108	blt	a8, a5, 1b
109
110
111	/* We have to flush and invalidate the caches here before we jump. */
112
113#if XCHAL_DCACHE_IS_WRITEBACK
114
115	___flush_dcache_all a5 a6
116
117#endif
118
119	___invalidate_icache_all a5 a6
120	isync
121
122	movi	a11, _reloc
123	jx	a11
124
125	.globl _reloc
126_reloc:
127
128	/* RedBoot is now at the end of the memory, so we don't have
129	 * to copy the parameter list. Keep the code around; in case
130	 * we need it again. */
131#if 0
132	# a0: load address
133	# a2: start address of parameter list
134	# a3: length of parameter list
135	# a4: __start
136
137	/* copy the parameter list out of the way */
138
139	movi	a6, _param_start
140	add	a3, a2, a3
1412:
142	l32i	a8, a2, 0
143	s32i	a8, a6, 0
144	addi	a2, a2, 4
145	addi	a6, a6, 4
146	blt	a2, a3, 2b
147#endif
148
149	/* clear BSS section */
150	movi	a6, __bss_start
151	movi	a7, __bss_end
152	movi.n	a5, 0
1533:
154	s32i	a5, a6, 0
155	addi	a6, a6, 4
156	blt	a6, a7, 3b
157
158	movi	a5, -16
159	movi	a1, _stack + STACK_SIZE
160	and	a1, a1, a5
161
162	/* Uncompress the kernel */
163
164	# a0: load address
165	# a2: boot parameter
166	# a4: __start
167
168	movi	a3, __image_load
169	sub	a4, a3, a4
170	add	a8, a0, a4
171
172	# a1  Stack
173	# a8(a4)  Load address of the image
174
175	movi	a6, _image_start
176	movi	a10, _image_end
177	movi	a7, 0x1000000
178	sub	a11, a10, a6
179	movi	a9, complen
180	s32i	a11, a9, 0
181
182	movi	a0, 0
183
184	# a6 destination
185	# a7 maximum size of destination
186	# a8 source
187	# a9 ptr to length
188
189	.extern gunzip
190	movi	a4, gunzip
191	beqz	a4, 1f
192
193	callx4	a4
194
195	j	2f
196
197
198	# a6 destination start
199	# a7 maximum size of destination
200	# a8 source start
201	# a9 ptr to length
202	# a10 destination end
203
2041:
205        l32i    a9, a8, 0
206        l32i    a11, a8, 4
207        s32i    a9, a6, 0
208        s32i    a11, a6, 4
209        l32i    a9, a8, 8
210        l32i    a11, a8, 12
211        s32i    a9, a6, 8
212        s32i    a11, a6, 12
213        addi    a6, a6, 16
214        addi    a8, a8, 16
215        blt     a6, a10, 1b
216
217
218	/* jump to the kernel */
2192:
220#if XCHAL_DCACHE_IS_WRITEBACK
221
222	___flush_dcache_all a5 a6
223
224#endif
225
226	___invalidate_icache_all a5 a6
227
228	isync
229
230	# a2  Boot parameter list
231
232	movi	a0, _image_start
233	jx	a0
234
235	.align 16
236	.data
237	.globl avail_ram
238avail_ram:
239	.long	_heap
240	.globl end_avail
241end_avail:
242	.long	_heap + HEAP_SIZE
243
244	.comm _stack, STACK_SIZE
245	.comm _heap, HEAP_SIZE
246
247	.globl end_avail
248	.comm complen, 4
249
250	.end	literal_prefix
251