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	/*
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	.literal_position
46	.begin literal_prefix .text
47
48	/* put literals in here! */
49
50	.globl _start
51_start:
52
53	/* 'reset' window registers */
54
55	movi	a4, 1
56	wsr	a4, ps
57	rsync
58
59	rsr	a5, windowbase
60	ssl	a5
61	sll	a4, a4
62	wsr	a4, windowstart
63	rsync
64
65	movi	a4, 0x00040000
66	wsr	a4, ps
67	rsync
68
69	/* copy the loader to its address
70	 * Note: The loader itself is a very small piece, so we assume we
71	 *       don't partially overlap. We also assume (even more important)
72	 *	 that the kernel image is out of the way. Usually, when the
73	 *	 load address of this image is not at an arbitrary address,
74	 *	 but aligned to some 10K's we shouldn't overlap.
75	 */
76
77	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
78	   l32r, so we load to a4 first. */
79
80	# addi	a4, a0, __start - __start_a0
81	# mov	a0, a4
82
83	movi	a4, __start
84	movi	a5, __start_a0
85	add	a4, a0, a4
86	sub	a0, a4, a5
87
88	movi	a4, __start
89	movi	a5, __reloc_end
90
91	# a0: address where this code has been loaded
92	# a4: compiled address of __start
93	# a5: compiled end address
94
95	mov.n	a7, a0
96	mov.n	a8, a4
97
981:
99	l32i	a10, a7, 0
100	l32i	a11, a7, 4
101	s32i	a10, a8, 0
102	s32i	a11, a8, 4
103	l32i	a10, a7, 8
104	l32i	a11, a7, 12
105	s32i	a10, a8, 8
106	s32i	a11, a8, 12
107	addi	a8, a8, 16
108	addi	a7, a7, 16
109	blt	a8, a5, 1b
110
111
112	/* We have to flush and invalidate the caches here before we jump. */
113
114#if XCHAL_DCACHE_IS_WRITEBACK
115
116	___flush_dcache_all a5 a6
117
118#endif
119
120	___invalidate_icache_all a5 a6
121	isync
122
123	movi	a11, _reloc
124	jx	a11
125
126	.globl _reloc
127_reloc:
128
129	/* RedBoot is now at the end of the memory, so we don't have
130	 * to copy the parameter list. Keep the code around; in case
131	 * we need it again. */
132#if 0
133	# a0: load address
134	# a2: start address of parameter list
135	# a3: length of parameter list
136	# a4: __start
137
138	/* copy the parameter list out of the way */
139
140	movi	a6, _param_start
141	add	a3, a2, a3
1422:
143	l32i	a8, a2, 0
144	s32i	a8, a6, 0
145	addi	a2, a2, 4
146	addi	a6, a6, 4
147	blt	a2, a3, 2b
148#endif
149
150	/* clear BSS section */
151	movi	a6, __bss_start
152	movi	a7, __bss_end
153	movi.n	a5, 0
1543:
155	s32i	a5, a6, 0
156	addi	a6, a6, 4
157	blt	a6, a7, 3b
158
159	movi	a5, -16
160	movi	a1, _stack + STACK_SIZE
161	and	a1, a1, a5
162
163	/* Uncompress the kernel */
164
165	# a0: load address
166	# a2: boot parameter
167	# a4: __start
168
169	movi	a3, __image_load
170	sub	a4, a3, a4
171	add	a8, a0, a4
172
173	# a1  Stack
174	# a8(a4)  Load address of the image
175
176	movi	a6, _image_start
177	movi	a10, _image_end
178	movi	a7, 0x1000000
179	sub	a11, a10, a6
180	movi	a9, complen
181	s32i	a11, a9, 0
182
183	movi	a0, 0
184
185	# a6 destination
186	# a7 maximum size of destination
187	# a8 source
188	# a9 ptr to length
189
190	.extern gunzip
191	movi	a4, gunzip
192	beqz	a4, 1f
193
194	callx4	a4
195
196	j	2f
197
198
199	# a6 destination start
200	# a7 maximum size of destination
201	# a8 source start
202	# a9 ptr to length
203	# a10 destination end
204
2051:
206        l32i    a9, a8, 0
207        l32i    a11, a8, 4
208        s32i    a9, a6, 0
209        s32i    a11, a6, 4
210        l32i    a9, a8, 8
211        l32i    a11, a8, 12
212        s32i    a9, a6, 8
213        s32i    a11, a6, 12
214        addi    a6, a6, 16
215        addi    a8, a8, 16
216        blt     a6, a10, 1b
217
218
219	/* jump to the kernel */
2202:
221#if XCHAL_DCACHE_IS_WRITEBACK
222
223	___flush_dcache_all a5 a6
224
225#endif
226
227	___invalidate_icache_all a5 a6
228
229	isync
230
231	# a2  Boot parameter list
232
233	movi	a0, _image_start
234	jx	a0
235
236	.align 16
237	.data
238	.globl avail_ram
239avail_ram:
240	.long	_heap
241	.globl end_avail
242end_avail:
243	.long	_heap + HEAP_SIZE
244
245	.comm _stack, STACK_SIZE
246	.comm _heap, HEAP_SIZE
247
248	.globl end_avail
249	.comm complen, 4
250
251	.end	literal_prefix
252