forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
4.6 KiB
251 lines
4.6 KiB
/* SPDX-License-Identifier: GPL-2.0 */ |
|
#include <asm/core.h> |
|
#include <asm/regs.h> |
|
#include <asm/asmmacro.h> |
|
#include <asm/cacheasm.h> |
|
/* |
|
* RB-Data: RedBoot data/bss |
|
* P: Boot-Parameters |
|
* L: Kernel-Loader |
|
* |
|
* The Linux-Kernel image including the loader must be loaded |
|
* to a position so that the kernel and the boot parameters |
|
* can fit in the space before the load address. |
|
* ______________________________________________________ |
|
* |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______| |
|
* ^ |
|
* ^ Load address |
|
* ______________________________________________________ |
|
* |___Linux-Kernel___|_P_|_L_|___________________________| |
|
* |
|
* The loader copies the parameter to the position that will |
|
* be the end of the kernel and itself to the end of the |
|
* parameter list. |
|
*/ |
|
|
|
/* Make sure we have enough space for the 'uncompressor' */ |
|
|
|
#define STACK_SIZE 32768 |
|
#define HEAP_SIZE (131072*4) |
|
|
|
# a2: Parameter list |
|
# a3: Size of parameter list |
|
|
|
.section .start, "ax" |
|
|
|
.globl __start |
|
/* this must be the first byte of the loader! */ |
|
__start: |
|
entry sp, 32 # we do not intend to return |
|
_call0 _start |
|
__start_a0: |
|
.align 4 |
|
|
|
.section .text, "ax" |
|
.literal_position |
|
.begin literal_prefix .text |
|
|
|
/* put literals in here! */ |
|
|
|
.globl _start |
|
_start: |
|
|
|
/* 'reset' window registers */ |
|
|
|
movi a4, 1 |
|
wsr a4, ps |
|
rsync |
|
|
|
rsr a5, windowbase |
|
ssl a5 |
|
sll a4, a4 |
|
wsr a4, windowstart |
|
rsync |
|
|
|
movi a4, 0x00040000 |
|
wsr a4, ps |
|
rsync |
|
|
|
/* copy the loader to its address |
|
* Note: The loader itself is a very small piece, so we assume we |
|
* don't partially overlap. We also assume (even more important) |
|
* that the kernel image is out of the way. Usually, when the |
|
* load address of this image is not at an arbitrary address, |
|
* but aligned to some 10K's we shouldn't overlap. |
|
*/ |
|
|
|
/* Note: The assembler cannot relax "addi a0, a0, ..." to an |
|
l32r, so we load to a4 first. */ |
|
|
|
# addi a4, a0, __start - __start_a0 |
|
# mov a0, a4 |
|
|
|
movi a4, __start |
|
movi a5, __start_a0 |
|
add a4, a0, a4 |
|
sub a0, a4, a5 |
|
|
|
movi a4, __start |
|
movi a5, __reloc_end |
|
|
|
# a0: address where this code has been loaded |
|
# a4: compiled address of __start |
|
# a5: compiled end address |
|
|
|
mov.n a7, a0 |
|
mov.n a8, a4 |
|
|
|
1: |
|
l32i a10, a7, 0 |
|
l32i a11, a7, 4 |
|
s32i a10, a8, 0 |
|
s32i a11, a8, 4 |
|
l32i a10, a7, 8 |
|
l32i a11, a7, 12 |
|
s32i a10, a8, 8 |
|
s32i a11, a8, 12 |
|
addi a8, a8, 16 |
|
addi a7, a7, 16 |
|
blt a8, a5, 1b |
|
|
|
|
|
/* We have to flush and invalidate the caches here before we jump. */ |
|
|
|
#if XCHAL_DCACHE_IS_WRITEBACK |
|
|
|
___flush_dcache_all a5 a6 |
|
|
|
#endif |
|
|
|
___invalidate_icache_all a5 a6 |
|
isync |
|
|
|
movi a11, _reloc |
|
jx a11 |
|
|
|
.globl _reloc |
|
_reloc: |
|
|
|
/* RedBoot is now at the end of the memory, so we don't have |
|
* to copy the parameter list. Keep the code around; in case |
|
* we need it again. */ |
|
#if 0 |
|
# a0: load address |
|
# a2: start address of parameter list |
|
# a3: length of parameter list |
|
# a4: __start |
|
|
|
/* copy the parameter list out of the way */ |
|
|
|
movi a6, _param_start |
|
add a3, a2, a3 |
|
2: |
|
l32i a8, a2, 0 |
|
s32i a8, a6, 0 |
|
addi a2, a2, 4 |
|
addi a6, a6, 4 |
|
blt a2, a3, 2b |
|
#endif |
|
|
|
/* clear BSS section */ |
|
movi a6, __bss_start |
|
movi a7, __bss_end |
|
movi.n a5, 0 |
|
3: |
|
s32i a5, a6, 0 |
|
addi a6, a6, 4 |
|
blt a6, a7, 3b |
|
|
|
movi a5, -16 |
|
movi a1, _stack + STACK_SIZE |
|
and a1, a1, a5 |
|
|
|
/* Uncompress the kernel */ |
|
|
|
# a0: load address |
|
# a2: boot parameter |
|
# a4: __start |
|
|
|
movi a3, __image_load |
|
sub a4, a3, a4 |
|
add a8, a0, a4 |
|
|
|
# a1 Stack |
|
# a8(a4) Load address of the image |
|
|
|
movi a6, _image_start |
|
movi a10, _image_end |
|
movi a7, 0x1000000 |
|
sub a11, a10, a6 |
|
movi a9, complen |
|
s32i a11, a9, 0 |
|
|
|
movi a0, 0 |
|
|
|
# a6 destination |
|
# a7 maximum size of destination |
|
# a8 source |
|
# a9 ptr to length |
|
|
|
.extern gunzip |
|
movi a4, gunzip |
|
beqz a4, 1f |
|
|
|
callx4 a4 |
|
|
|
j 2f |
|
|
|
|
|
# a6 destination start |
|
# a7 maximum size of destination |
|
# a8 source start |
|
# a9 ptr to length |
|
# a10 destination end |
|
|
|
1: |
|
l32i a9, a8, 0 |
|
l32i a11, a8, 4 |
|
s32i a9, a6, 0 |
|
s32i a11, a6, 4 |
|
l32i a9, a8, 8 |
|
l32i a11, a8, 12 |
|
s32i a9, a6, 8 |
|
s32i a11, a6, 12 |
|
addi a6, a6, 16 |
|
addi a8, a8, 16 |
|
blt a6, a10, 1b |
|
|
|
|
|
/* jump to the kernel */ |
|
2: |
|
#if XCHAL_DCACHE_IS_WRITEBACK |
|
|
|
___flush_dcache_all a5 a6 |
|
|
|
#endif |
|
|
|
___invalidate_icache_all a5 a6 |
|
|
|
isync |
|
|
|
# a2 Boot parameter list |
|
|
|
movi a0, _image_start |
|
jx a0 |
|
|
|
.align 16 |
|
.data |
|
.globl avail_ram |
|
avail_ram: |
|
.long _heap |
|
.globl end_avail |
|
end_avail: |
|
.long _heap + HEAP_SIZE |
|
|
|
.comm _stack, STACK_SIZE |
|
.comm _heap, HEAP_SIZE |
|
|
|
.globl end_avail |
|
.comm complen, 4 |
|
|
|
.end literal_prefix
|
|
|