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