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 
70 KABI_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 
101 1:
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
145 2:
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
157 3:
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 
208 1:
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 */
223 2:
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 
236 KABI_C0	mov	abi_arg0, abi_saved0
237 	movi	a0, _image_start
238 	jx	a0
239 
240 	.align 16
241 	.data
242 	.globl avail_ram
243 avail_ram:
244 	.long	_heap
245 	.globl end_avail
246 end_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