Basic elfboot functionality is in now.

We're trying to avoid the bounce buffer mess, which is really complex, 
by running elfboot out of the boot block. This code includes a really 
dumb allocator in elfboot which may or may not work. It basically
allocates off the elfboot() stack. 

This builds, but elfboot is not tested. That's next. 
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>



git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@102 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Ronald G. Minnich 2007-02-23 13:39:07 +00:00
parent 83ac9292bd
commit 08016c4ca8
6 changed files with 67 additions and 17 deletions

View file

@ -75,16 +75,19 @@ $(obj)/stage0.init:
$(Q)# console lib
$(Q)$(CC) $(INITCFLAGS) -c $(src)/arch/x86/console.c -o $(obj)/console.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/arch/x86/serial.c -o $(obj)/serial.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/arch/x86/archelfboot.c -o $(obj)/archelfboot.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/console/vtxprintf.c -o $(obj)/vtxprintf.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/console/vsprintf.c -o $(obj)/vsprintf.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/uart8250.c -o $(obj)/uart8250.o
$(Q)# other lib parts
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/mem.c -o $(obj)/mem.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/elfboot.c -o $(obj)/elfboot.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/compute_ip_checksum.c -o $(obj)/compute_ip_checksum.o
$(Q)cd $(obj); $(CC) -m32 -nostdlib -static \
-T $(src)/arch/x86/ldscript.ld cachemain.o \
console.o uart8250.o serial.o vtxprintf.o \
vsprintf.o lar.o mem.o stage0_i586.o -o stage0.o
console.o uart8250.o serial.o archelfboot.o vtxprintf.o \
vsprintf.o lar.o elfboot.o compute_ip_checksum.o mem.o stage0_i586.o -o stage0.o
$(Q)objcopy -O binary $(obj)/stage0.o $(obj)/stage0.init.pre
@ -115,8 +118,6 @@ $(obj)/linuxbios.stage2: $(obj)/stage0.init $(obj)/statictree.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/device/device.c -o $(obj)/device.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/device/device_util.c -o $(obj)/device_util.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/device/root_device.c -o $(obj)/root_device.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/elfboot.c -o $(obj)/elfboot.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/compute_ip_checksum.c -o $(obj)/compute_ip_checksum.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/mem.c -o $(obj)/mem.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/malloc.c -o $(obj)/malloc.o
$(Q)$(CC) $(INITCFLAGS) -c $(src)/lib/clog2.c -o $(obj)/clog2.o

View file

@ -69,6 +69,7 @@ int elf_check_arch(Elf_ehdr *ehdr)
void jmp_to_elf_entry(void *entry)
{
#ifdef NOTYET
extern unsigned char _ram_seg, _eram_seg;
unsigned long lb_start, lb_size;
unsigned long adjusted_boot_notes;
@ -83,12 +84,11 @@ void jmp_to_elf_entry(void *entry)
adjusted_boot_notes = (unsigned long)&elf_boot_notes;
printk_spew("entry = 0x%08lx\n", (unsigned long)entry);
printk_spew("lb_start = 0x%08lx\n", lb_start);
printk_spew("lb_size = 0x%08lx\n", lb_size);
printk_spew("buffer = 0x%08lx\n", buffer);
printk_spew(" elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
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, " elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
printk(BIOS_SPEW, "adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
/* Jump to kernel */
__asm__ __volatile__(
@ -174,6 +174,7 @@ void jmp_to_elf_entry(void *entry)
"g" (lb_start), "g" (buffer), "g" (lb_size),
"g" (entry), "g"(adjusted_boot_notes)
);
#endif
}

View file

@ -22,6 +22,7 @@
#include <console/console.h>
#include <console/loglevel.h>
#include <lar.h>
#include <linuxbios_tables.h>
#include "config.h"
/* these prototypes should go into headers */
@ -61,7 +62,9 @@ void stage1_main(u32 bist)
{
int ret;
struct mem_file archive;
int elfboot_mem(struct lb_memory *mem, void *where, int size);
/* HACK -- fake memory table for now */
struct lb_memory mem = {LB_TAG_MEMORY, 1, .map = { {0, 32*1024*1024, LB_MEM_RAM}}};
post_code(0x02);
// before we do anything, we want to stop if we dont run
@ -210,6 +213,16 @@ printk(BIOS_INFO, "Start search at 0x%x, size %d\n", archive.start, archive.len)
printk(BIOS_INFO, "Done stage2 code\n");
ret = find_file(&archive, "payload", &result);
if (ret) {
printk(BIOS_INFO, "no such name %s\n", "payload");
die("cachemain finding payload");
}
ret = elfboot_mem(&mem, result.start, result.len);
printk("elfboot_mem returns %d\n", ret);
die ("FATAL: This is as far as it goes\n");
}

View file

@ -390,7 +390,7 @@ typedef Elf64_Phdr Elf_phdr;
#endif
extern int elf_check_arch(Elf_ehdr *ehdr);
extern void jmp_to_elf_entry(void *entry, unsigned long buffer);
extern void jmp_to_elf_entry(void *entry);
struct lb_memory;
extern int elfboot(struct lb_memory *mem);

View file

@ -41,4 +41,3 @@ struct mem_file {
int find_file(struct mem_file *archive, char *filename, struct mem_file *result);
int copy_file(struct mem_file *archive, char *filename, void *where);
int run_file(struct mem_file *archive, char *filename, void *where);

View file

@ -32,13 +32,39 @@ struct ip_checksum_vcb {
unsigned short ip_checksum;
};
/* we're trying to keep out of the way of elf segments, without requiring the
* bounce buffer. This may fail, but it's worth the effort.
*/
static unsigned char *arena;
int arenasize;
static void
setupmalloc(void *s, int size)
{
arena = s;
arenasize = size;
}
static void *localmalloc(int nbytes)
{
char *ret;
if (nbytes > arenasize)
return NULL;
arenasize -= nbytes;
ret = arena;
arena += nbytes;
return ret;
}
/* streams are a nice way to abstract the pointer/size-based nature of the
* memory away. The main good part is that we have a way to fail out if the
* elfboot code is running off the end of the array for some reason. So we won't
* rip it out just yet.
*/
unsigned char *streambase = NULL;
int streamsize = -1;
static unsigned char *streambase = NULL;
static int streamsize = -1;
int stream_init(void){
return 0;
@ -143,7 +169,7 @@ static struct verify_callback *process_elf_notes(
case EIN_PROGRAM_CHECKSUM:
{
struct ip_checksum_vcb *cb;
cb = malloc(sizeof(*cb));
cb = localmalloc(sizeof(*cb));
cb->ip_checksum = *((uint16_t *)n_desc);
cb->data.callback = verify_ip_checksum;
cb->data.next = cb_chain;
@ -231,7 +257,7 @@ static int build_elf_segment_list(
printk(BIOS_DEBUG, "Dropping empty segment\n");
continue;
}
new = malloc(sizeof(*new));
new = localmalloc(sizeof(*new));
new->s_addr = phdr[i].p_paddr;
new->s_memsz = phdr[i].p_memsz;
new->s_offset = phdr[i].p_offset;
@ -446,7 +472,10 @@ int elfboot(struct lb_memory *mem)
static unsigned char header[ELF_HEAD_SIZE];
int header_offset;
int i, result;
/* for stupid allocator which won't run into trouble with segments */
char alloc[256];
setupmalloc(alloc, sizeof(alloc));
result = 0;
printk(BIOS_INFO, "\n");
printk(BIOS_INFO, "Welcome to %s, the open sourced starter.\n", BOOTLOADER);
@ -508,3 +537,10 @@ int elfboot(struct lb_memory *mem)
return 0;
}
int elfboot_mem(struct lb_memory *mem, void *where, int size)
{
streambase = where;
streamsize = size;
return elfboot(mem);
}