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