From 08016c4ca860b3ee24d0bc93e03944235e596fc0 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Fri, 23 Feb 2007 13:39:07 +0000 Subject: [PATCH] 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 Acked-by: Ronald G. Minnich Acked-by: Stefan Reinauer git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@102 f3766cd6-281f-0410-b1cd-43a5c92072e9 --- arch/x86/Makefile | 9 +++++---- arch/x86/archelfboot.c | 13 +++++++------ arch/x86/cachemain.c | 15 +++++++++++++- include/elf.h | 2 +- include/lar.h | 1 - lib/elfboot.c | 44 ++++++++++++++++++++++++++++++++++++++---- 6 files changed, 67 insertions(+), 17 deletions(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 30eba5b981..ef09d27793 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -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 diff --git a/arch/x86/archelfboot.c b/arch/x86/archelfboot.c index bcf363d048..d9a8314fd8 100644 --- a/arch/x86/archelfboot.c +++ b/arch/x86/archelfboot.c @@ -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 } diff --git a/arch/x86/cachemain.c b/arch/x86/cachemain.c index 0b5cc92e44..d5c41b8a5d 100644 --- a/arch/x86/cachemain.c +++ b/arch/x86/cachemain.c @@ -22,6 +22,7 @@ #include #include #include +#include #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"); } diff --git a/include/elf.h b/include/elf.h index eaf9c67837..9f143bc23e 100644 --- a/include/elf.h +++ b/include/elf.h @@ -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); diff --git a/include/lar.h b/include/lar.h index 7111f5e5fb..5d1a8811a5 100644 --- a/include/lar.h +++ b/include/lar.h @@ -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); - diff --git a/lib/elfboot.c b/lib/elfboot.c index f2c64f8296..6c545efdce 100644 --- a/lib/elfboot.c +++ b/lib/elfboot.c @@ -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); +}