diff options
Diffstat (limited to 'kexec/arch/mips/mips-setup-simple.S')
-rw-r--r-- | kexec/arch/mips/mips-setup-simple.S | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/kexec/arch/mips/mips-setup-simple.S b/kexec/arch/mips/mips-setup-simple.S new file mode 100644 index 0000000..1acdee3 --- /dev/null +++ b/kexec/arch/mips/mips-setup-simple.S @@ -0,0 +1,110 @@ +/* + * mips-setup-simple.S - code to execute before kernel to handle command line + * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini + * Copyright (C) 2007 Tvblob s.r.l. + * + * derived from Albert Herranz idea (ppc) adding command line support + * (boot_notes structure) + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +/* + * Only suitable for platforms booting with MMU turned off. + * -- Albert Herranz + */ +#include "regdef.h" + +/* returns t0 = relocated address of sym */ +/* modifies t1 t2 */ +/* sym must not be global or this will not work (at least AFAIK up to now) */ +#define RELOC_SYM(sym) \ + move t0,ra; /* save ra */ \ + bal 1f; \ +1: \ + move t1,ra; /* now t1 is 1b (where we are now) */ \ + move ra,t0; /* restore ra */ \ + lui t2,%hi(1b); \ + ori t2,t2,%lo(1b); \ + lui t0,%hi(sym); \ + ori t0,t0,%lo(sym); \ + sub t0,t0,t2; /* t0 = offset between sym and 1b */ \ + add t0,t1,t0; /* t0 = actual address in memory */ + + .data + .globl setup_simple_start +setup_simple_start: + + /* should perform here any required setup */ + + /* Initialize GOT pointer (verify if needed) */ + bal 1f + nop + .word _GLOBAL_OFFSET_TABLE_ + 1: + move gp, ra + lw t1, 0(ra) + move gp, t1 + + /* spr8 relocation */ + RELOC_SYM(spr8) + + move t4,t0 // save pointer to kernel start addr + lw t3,0(t0) // save kernel start address + + /* spr9 relocation */ + RELOC_SYM(spr9) + lw a0,0(t0) // load argc + + // this code is to be changed if boot_notes struct changes + lw t2,12(t4) // t2 is size of boot_notes struct + addi t2,t2,3 + srl t2,t2,2 + sll v1,t2,2 // v1 = size of boot_notes struct + // aligned to word boundary + + addi t0,t4,0x20 // t0 contains the address of "kexec" string + add v0,t4,v1 // v0 points to last word of boot_notes + addi v0,v0,8 // v0 points to address after boot_notes + sw t0,0(v0) // store pointer to "kexec" string there + + lw t2,-8(t0) // t2 is size of "kexec" string in bytes + addi t2,t2,3 + srl t2,t2,2 + sll v1,t2,2 // v1 = size of "kexec" string + // aligned to word boundary + add t2,t0,v1 + addi t0,t2,4 // t0 points to size of version string + + lw t2,0(t0) // t2 is size of version string in bytes + addi t2,t2,3 + srl t2,t2,2 + sll v1,t2,2 // v1 = size of version string + // aligned to word boundary + + addi t0,t0,8 // t0 points to version string + add t0,t0,v1 // t0 points to start of command_line record + addi t0,t0,12 // t0 points command line + + sw t0,4(v0) // store pointer to command line + + move a1,v0 // load argv + li a2,0 + li a3,0 + + jr t3 + nop + + .balign 4 + .globl setup_simple_regs +setup_simple_regs: +spr8: .long 0x00000000 +spr9: .long 0x00000000 + +setup_simple_end: + + .globl setup_simple_size +setup_simple_size: + .long setup_simple_end - setup_simple_start + |