2003-04-22 21:02:15 +02:00
|
|
|
#include <console/console.h>
|
2013-05-25 00:09:36 +02:00
|
|
|
#include <arch/stages.h>
|
2015-03-17 17:43:44 +01:00
|
|
|
#include <program_loading.h>
|
2003-04-22 21:02:15 +02:00
|
|
|
#include <ip_checksum.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-02-09 00:28:04 +01:00
|
|
|
/* When the ramstage is relocatable the elf loading ensures an elf image cannot
|
|
|
|
* be loaded over the ramstage code. */
|
2014-02-25 05:27:39 +01:00
|
|
|
static void jmp_payload_no_bounce_buffer(void *entry)
|
2013-02-09 00:28:04 +01:00
|
|
|
{
|
|
|
|
/* Jump to kernel */
|
|
|
|
__asm__ __volatile__(
|
|
|
|
" cld \n\t"
|
|
|
|
/* Now jump to the loaded image */
|
|
|
|
" call *%0\n\t"
|
|
|
|
|
|
|
|
/* The loaded image returned? */
|
|
|
|
" cli \n\t"
|
|
|
|
" cld \n\t"
|
|
|
|
|
|
|
|
::
|
2013-05-28 23:15:01 +02:00
|
|
|
"r" (entry)
|
2013-02-09 00:28:04 +01:00
|
|
|
);
|
|
|
|
}
|
2014-02-25 05:27:39 +01:00
|
|
|
|
|
|
|
static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
extern unsigned char _ram_seg, _eram_seg;
|
|
|
|
unsigned long lb_start, lb_size;
|
|
|
|
|
|
|
|
lb_start = (unsigned long)&_ram_seg;
|
|
|
|
lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
|
|
|
|
|
2010-03-22 12:42:32 +01:00
|
|
|
printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
|
|
|
|
printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
|
|
|
|
printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
|
|
|
|
printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);
|
2010-04-27 08:56:47 +02:00
|
|
|
|
2003-04-22 21:02:15 +02:00
|
|
|
/* Jump to kernel */
|
|
|
|
__asm__ __volatile__(
|
|
|
|
" cld \n\t"
|
|
|
|
/* Save the callee save registers... */
|
|
|
|
" pushl %%esi\n\t"
|
|
|
|
" pushl %%edi\n\t"
|
|
|
|
" pushl %%ebx\n\t"
|
|
|
|
/* Save the parameters I was passed */
|
|
|
|
" pushl $0\n\t" /* 20 adjust */
|
|
|
|
" pushl %0\n\t" /* 16 lb_start */
|
|
|
|
" pushl %1\n\t" /* 12 buffer */
|
|
|
|
" pushl %2\n\t" /* 8 lb_size */
|
|
|
|
" pushl %3\n\t" /* 4 entry */
|
|
|
|
" pushl %4\n\t" /* 0 elf_boot_notes */
|
|
|
|
/* Compute the adjustment */
|
|
|
|
" xorl %%eax, %%eax\n\t"
|
|
|
|
" subl 16(%%esp), %%eax\n\t"
|
|
|
|
" addl 12(%%esp), %%eax\n\t"
|
|
|
|
" addl 8(%%esp), %%eax\n\t"
|
|
|
|
" movl %%eax, 20(%%esp)\n\t"
|
2009-03-31 19:17:30 +02:00
|
|
|
/* Place a copy of coreboot in its new location */
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Move ``longs'' the coreboot size is 4 byte aligned */
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl 12(%%esp), %%edi\n\t"
|
|
|
|
" addl 8(%%esp), %%edi\n\t"
|
|
|
|
" movl 16(%%esp), %%esi\n\t"
|
|
|
|
" movl 8(%%esp), %%ecx\n\n"
|
|
|
|
" shrl $2, %%ecx\n\t"
|
|
|
|
" rep movsl\n\t"
|
|
|
|
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Adjust the stack pointer to point into the new coreboot image */
|
2003-04-22 21:02:15 +02:00
|
|
|
" addl 20(%%esp), %%esp\n\t"
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Adjust the instruction pointer to point into the new coreboot image */
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl $1f, %%eax\n\t"
|
|
|
|
" addl 20(%%esp), %%eax\n\t"
|
|
|
|
" jmp *%%eax\n\t"
|
|
|
|
"1: \n\t"
|
|
|
|
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Copy the coreboot bounce buffer over coreboot */
|
|
|
|
/* Move ``longs'' the coreboot size is 4 byte aligned */
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl 16(%%esp), %%edi\n\t"
|
|
|
|
" movl 12(%%esp), %%esi\n\t"
|
|
|
|
" movl 8(%%esp), %%ecx\n\t"
|
|
|
|
" shrl $2, %%ecx\n\t"
|
|
|
|
" rep movsl\n\t"
|
|
|
|
|
|
|
|
/* Now jump to the loaded image */
|
2008-11-11 21:20:54 +01:00
|
|
|
" movl %5, %%eax\n\t"
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl 0(%%esp), %%ebx\n\t"
|
|
|
|
" call *4(%%esp)\n\t"
|
|
|
|
|
|
|
|
/* The loaded image returned? */
|
|
|
|
" cli \n\t"
|
|
|
|
" cld \n\t"
|
|
|
|
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Copy the saved copy of coreboot where coreboot runs */
|
|
|
|
/* Move ``longs'' the coreboot size is 4 byte aligned */
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl 16(%%esp), %%edi\n\t"
|
|
|
|
" movl 12(%%esp), %%esi\n\t"
|
|
|
|
" addl 8(%%esp), %%esi\n\t"
|
|
|
|
" movl 8(%%esp), %%ecx\n\t"
|
|
|
|
" shrl $2, %%ecx\n\t"
|
|
|
|
" rep movsl\n\t"
|
|
|
|
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Adjust the stack pointer to point into the old coreboot image */
|
2003-04-22 21:02:15 +02:00
|
|
|
" subl 20(%%esp), %%esp\n\t"
|
|
|
|
|
2008-01-18 16:08:58 +01:00
|
|
|
/* Adjust the instruction pointer to point into the old coreboot image */
|
2003-04-22 21:02:15 +02:00
|
|
|
" movl $1f, %%eax\n\t"
|
|
|
|
" subl 20(%%esp), %%eax\n\t"
|
|
|
|
" jmp *%%eax\n\t"
|
|
|
|
"1: \n\t"
|
|
|
|
|
|
|
|
/* Drop the parameters I was passed */
|
|
|
|
" addl $24, %%esp\n\t"
|
|
|
|
|
|
|
|
/* Restore the callee save registers */
|
|
|
|
" popl %%ebx\n\t"
|
|
|
|
" popl %%edi\n\t"
|
|
|
|
" popl %%esi\n\t"
|
|
|
|
|
2010-04-27 08:56:47 +02:00
|
|
|
::
|
2009-03-20 19:29:49 +01:00
|
|
|
"ri" (lb_start), "ri" (buffer), "ri" (lb_size),
|
|
|
|
"ri" (entry),
|
2013-05-25 00:09:36 +02:00
|
|
|
"ri"(0), "ri" (0)
|
2003-04-22 21:02:15 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-03-20 22:37:12 +01:00
|
|
|
static void try_payload(struct prog *prog)
|
2014-02-25 05:27:39 +01:00
|
|
|
{
|
2015-03-20 22:37:12 +01:00
|
|
|
if (prog->type == PROG_PAYLOAD) {
|
|
|
|
if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
|
|
|
|
jmp_payload_no_bounce_buffer(prog_entry(prog));
|
|
|
|
else
|
|
|
|
jmp_payload(prog_entry(prog),
|
|
|
|
(uintptr_t)prog_start(prog),
|
|
|
|
prog_size(prog));
|
|
|
|
}
|
2014-02-25 05:27:39 +01:00
|
|
|
}
|
2015-03-20 21:55:08 +01:00
|
|
|
|
|
|
|
void arch_prog_run(struct prog *prog)
|
|
|
|
{
|
2015-03-20 22:37:12 +01:00
|
|
|
if (ENV_RAMSTAGE)
|
|
|
|
try_payload(prog);
|
2015-03-20 21:55:08 +01:00
|
|
|
__asm__ volatile (
|
|
|
|
"jmp *%%edi\n"
|
|
|
|
:: "D"(prog_entry(prog))
|
|
|
|
);
|
|
|
|
}
|