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