From 327a4432fecbad25bfdd1e54ad095e1b08f08126 Mon Sep 17 00:00:00 2001 From: "Ronald G. Minnich" Date: Fri, 23 Feb 2007 19:53:11 +0000 Subject: [PATCH] newelfboot.c. this elfboot is tremendously simplified so it can run out of FLASH. Since it runs out of FLASH, we have removed the need for bounce buffer support. that in turn rips out all kinds of stuff, so it is now simpler. We're ripping out all the checksum stuff -- lar does that. lar.c has some debug prints removed. elfboot.c has some mods, but elfboot.c is going away. cachemain.c has a few mods for using newelfboot. Makefile reflects these changes. Not tested, I'm going to bed though, so here you are. Signed-off-by: Ronald G. Minnich Acked-by: Ronald G. Minnich Acked-by: Stefan Reinauer git-svn-id: svn://coreboot.org/repository/LinuxBIOSv3@108 f3766cd6-281f-0410-b1cd-43a5c92072e9 --- arch/x86/Makefile | 11 +- arch/x86/cachemain.c | 2 +- lib/elfboot.c | 13 +-- lib/lar.c | 2 - lib/newelfboot.c | 253 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 266 insertions(+), 15 deletions(-) create mode 100644 lib/newelfboot.c diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 9e6f39388b..0398177d69 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -49,7 +49,8 @@ $(obj)/linuxbios.lar: $(obj)/util/lar/lar lzma $(obj)/linuxbios.initram $(obj)/l $(Q)mkdir $(obj)/lar.tmp/normal $(Q)cp $(obj)/linuxbios.initram $(obj)/lar.tmp/normal/initram $(Q)cp $(obj)/linuxbios.stage2 $(obj)/lar.tmp/normal/stage2 - $(Q)cd $(obj)/lar.tmp && ../util/lar/lar c ../linuxbios.lar.pre normal/initram normal/stage2 + $(Q)cp $(PAYLOAD) $(obj)/lar.tmp/normal/payload + $(Q)cd $(obj)/lar.tmp && ../util/lar/lar c ../linuxbios.lar.pre normal/initram normal/stage2 normal/payload # TODO: dynamically pad the lar archive. bs is image size - bootblock size (8k) $(Q)dd if=$(obj)/linuxbios.lar.pre of=$(obj)/linuxbios.lar \ bs=245760 count=1 conv=sync $(SILENT) @@ -81,13 +82,13 @@ $(obj)/stage0.init: $(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/newelfboot.c -o $(obj)/newelfboot.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 archelfboot.o vtxprintf.o \ - vsprintf.o lar.o elfboot.o compute_ip_checksum.o mem.o stage0_i586.o -o stage0.o + vsprintf.o lar.o newelfboot.o compute_ip_checksum.o mem.o stage0_i586.o -o stage0.o $(Q)objcopy -O binary $(obj)/stage0.o $(obj)/stage0.init.pre @@ -128,8 +129,8 @@ $(obj)/linuxbios.stage2: $(obj)/stage0.init $(obj)/statictree.o $(Q)# leave a .o with full symbols in it for debugging. $(Q)cd $(obj); $(LD) -R $(obj)/stage0.o -Ttext 0x1000 \ --entry=stage2 -o $(obj)/linuxbios.stage2.o \ - stage2.o device.o device_util.o root_device.o elfboot.o \ - compute_ip_checksum.o mem.o malloc.o clog2.o mainboard.o \ + stage2.o device.o device_util.o root_device.o \ + mem.o malloc.o clog2.o mainboard.o \ statictree.o $(Q)objcopy -O binary $(obj)/linuxbios.stage2.o $(obj)/linuxbios.stage2 diff --git a/arch/x86/cachemain.c b/arch/x86/cachemain.c index b97672b5aa..8cd0257659 100644 --- a/arch/x86/cachemain.c +++ b/arch/x86/cachemain.c @@ -224,7 +224,7 @@ 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); + ret = find_file(&archive, "normal/payload", &result); if (ret) { printk(BIOS_INFO, "no such name %s\n", "payload"); die("cachemain finding payload"); diff --git a/lib/elfboot.c b/lib/elfboot.c index 717c8ddada..153d877c59 100644 --- a/lib/elfboot.c +++ b/lib/elfboot.c @@ -83,12 +83,12 @@ int stream_skip(int bytes){ } int stream_read(void *dest, int bytes) { +printk(BIOS_INFO, "read %d bytes %d left\n", bytes, streamsize); if (streamsize < bytes) return -1; memcpy(dest, streambase, bytes); - stream_skip(bytes); - return bytes; + return stream_skip(bytes); } int verify_ip_checksum( @@ -469,7 +469,7 @@ int elfload(struct lb_memory *mem, int elfboot(struct lb_memory *mem) { Elf_ehdr *ehdr; - static unsigned char header[ELF_HEAD_SIZE]; + unsigned char header[ELF_HEAD_SIZE]; int header_offset; int i, result; /* for stupid allocator which won't run into trouble with segments */ @@ -478,9 +478,7 @@ int elfboot(struct lb_memory *mem) setupmalloc(alloc, sizeof(alloc)); result = 0; printk(BIOS_INFO, "\n"); - printk(BIOS_INFO, "Welcome to %s, the open sourced starter.\n", BOOTLOADER); - printk(BIOS_INFO, "Version %s\n", BOOTLOADER_VERSION); - printk(BIOS_INFO, "\n"); + printk(BIOS_INFO, "Elfboot\n"); post_code(0xf8); if (stream_init() < 0) { @@ -490,7 +488,7 @@ int elfboot(struct lb_memory *mem) /* Read in the initial ELF_HEAD_SIZE bytes */ if (stream_read(header, ELF_HEAD_SIZE) != ELF_HEAD_SIZE) { - printk(BIOS_ERR, "Read failed...\n"); + printk(BIOS_ERR, "Header read failed...\n"); goto out; } /* Scan for an elf header */ @@ -542,5 +540,6 @@ int elfboot_mem(struct lb_memory *mem, void *where, int size) { streambase = where; streamsize = size; +printk(BIOS_INFO, "base %p, size %d\n", streambase, streamsize); return elfboot(mem); } diff --git a/lib/lar.c b/lib/lar.c index 5d77bb9583..14208ad78a 100644 --- a/lib/lar.c +++ b/lib/lar.c @@ -43,8 +43,6 @@ int find_file(struct mem_file *archive, char *filename, struct mem_file *result) printk(BIOS_INFO, "start 0x%x len 0x%x\n", archive->start, archive->len); for (walk = archive->start; walk < (char *)archive->start + archive->len; walk+=16) { -printk(BIOS_INFO, "in for loop *start is %x\n", *(unsigned long *) archive->start); -printk(BIOS_INFO, "walk is %s(%p)\n", walk, walk); if(strcmp(walk, MAGIC)!=0) continue; diff --git a/lib/newelfboot.c b/lib/newelfboot.c new file mode 100644 index 0000000000..e41ad0bb55 --- /dev/null +++ b/lib/newelfboot.c @@ -0,0 +1,253 @@ +#include +//#include +#include +#include +#include +#include +#include +#include +#include + +static int valid_area(struct lb_memory *mem, + unsigned long start, unsigned long len) +{ + /* Check through all of the memory segments and ensure + * the segment that was passed in is completely contained + * in RAM. + */ + int i; + unsigned long end = start + len; + unsigned long mem_entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]); + + /* Walk through the table of valid memory ranges and see if I + * have a match. + */ + for(i = 0; i < mem_entries; i++) { + uint64_t mstart, mend; + uint32_t mtype; + mtype = mem->map[i].type; + mstart = unpack_lb64(mem->map[i].start); + mend = mstart + unpack_lb64(mem->map[i].size); + if ((mtype == LB_MEM_RAM) && (start < mend) && (end > mstart)) { + break; + } + } + if (i == mem_entries) { + printk(BIOS_ERR, "No matching ram area found for range:\n"); + printk(BIOS_ERR, " [0x%016lx, 0x%016lx)\n", start, end); + printk(BIOS_ERR, "Ram areas\n"); + for(i = 0; i < mem_entries; i++) { + uint64_t mstart, mend; + uint32_t mtype; + mtype = mem->map[i].type; + mstart = unpack_lb64(mem->map[i].start); + mend = mstart + unpack_lb64(mem->map[i].size); + printk(BIOS_ERR, " [0x%016lx, 0x%016lx) %s\n", + (unsigned long)mstart, + (unsigned long)mend, + (mtype == LB_MEM_RAM)?"RAM":"Reserved"); + + } + return 0; + } + return 1; +} + +static int load_elf_segments(struct lb_memory *mem,Elf_phdr *phdr, int headers) +{ + struct segment *ptr; + int i; + int size; + unsigned char *header = (unsigned char *) phdr; + for(i = 0; i < headers; i++) { + struct segment *new; + /* Ignore data that I don't need to handle */ + if (phdr[i].p_type != PT_LOAD) { + printk(BIOS_DEBUG, "Dropping non PT_LOAD segment\n"); + continue; + } + if (phdr[i].p_memsz == 0) { + printk(BIOS_DEBUG, "Dropping empty segment\n"); + continue; + } + printk(BIOS_DEBUG, "New segment addr 0x%lx size 0x%lx offset 0x%lx filesize 0x%lx\n", + phdr[i].p_paddr, phdr[i].p_memsz, phdr[i].p_offset, phdr[i].p_filesz); + /* Clean up the values */ + size = phdr[i].p_filesz; + if (phdr[i].p_filesz > phdr[i].p_memsz) { + size = phdr[i].p_memsz; + } + printk(BIOS_DEBUG, "(cleaned up) New segment addr 0x%lx size 0x%lx offset 0x%lx\n", + phdr[i].p_paddr, size, phdr[i].p_offset); + + /* Verify the memory addresses in the segment are valid */ + if (!valid_area(mem, phdr[i].p_paddr, size)) + goto out; + /* let's just be stupid about this. Bzero the whole area we are copying to, + * then copy out the data, which may be a subset of the total area. + * the cache, after all, is your friend. + */ + memset((unsigned char *)phdr[i].p_paddr, 0, size); + /* ok, copy it out */ + memcpy((unsigned char *)phdr[i].p_paddr, &header[phdr[i].p_offset], size); + + } + return 1; + out: + return 0; +} + + + +int elfload(struct lb_memory *mem, + unsigned char *header, unsigned long header_size) +{ + Elf_ehdr *ehdr; + Elf_phdr *phdr; + void *entry; + void (*v)(void); + struct verify_callback *cb_chain; + + ehdr = (Elf_ehdr *)header; + entry = (void *)(ehdr->e_entry); + phdr = (Elf_phdr *)(&header[ehdr->e_phoff]); + + /* Load the segments */ + if (!load_elf_segments(mem, phdr, header_size)) + goto out; + + printk(BIOS_SPEW, "Loaded segments\n"); + + printk(BIOS_SPEW, "closed down stream\n"); + /* Reset to booting from this image as late as possible */ + /* what the hell is boot_successful? */ + //boot_successful(); + + printk(BIOS_DEBUG, "Jumping to boot code at 0x%x\n", entry); + post_code(0xfe); + + /* Jump to kernel */ + /* just call it as a function. If it wants to return, it will. */ + v = entry; + v(); + return 1; + + out: + return 0; +} + +#ifdef NOT +int elfboot(struct lb_memory *mem) +{ + Elf_ehdr *ehdr; + unsigned char header[ELF_HEAD_SIZE]; + int header_offset; + int i, result; + + result = 0; + printk(BIOS_INFO, "\n"); + printk(BIOS_INFO, "Elfboot\n"); + post_code(0xf8); + + /* Read in the initial ELF_HEAD_SIZE bytes */ + if (stream_read(header, ELF_HEAD_SIZE) != ELF_HEAD_SIZE) { + printk(BIOS_ERR, "Header read failed...\n"); + goto out; + } + /* Scan for an elf header */ + header_offset = -1; + for(i = 0; i < ELF_HEAD_SIZE - (sizeof(Elf_ehdr) + sizeof(Elf_phdr)); i+=16) { + ehdr = (Elf_ehdr *)(&header[i]); + if (memcmp(ehdr->e_ident, ELFMAG, 4) != 0) { + printk(BIOS_SPEW, "NO header at %d\n", i); + continue; + } + printk(BIOS_DEBUG, "Found ELF candidate at offset %d\n", i); + /* Sanity check the elf header */ + if ((ehdr->e_type == ET_EXEC) && + elf_check_arch(ehdr) && + (ehdr->e_ident[EI_VERSION] == EV_CURRENT) && + (ehdr->e_version == EV_CURRENT) && + (ehdr->e_ehsize == sizeof(Elf_ehdr)) && + (ehdr->e_phentsize = sizeof(Elf_phdr)) && + (ehdr->e_phoff < (ELF_HEAD_SIZE - i)) && + ((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) <= + (ELF_HEAD_SIZE - i))) { + header_offset = i; + break; + } + ehdr = 0; + } + printk(BIOS_SPEW, "header_offset is %d\n", header_offset); + if (header_offset == -1) { + goto out; + } + + printk(BIOS_SPEW, "Try to load at offset 0x%x\n", header_offset); + result = elfload(mem, + header + header_offset , ELF_HEAD_SIZE - header_offset); + out: + if (!result) { + /* Shutdown the stream device */ + + printk(BIOS_ERR, "Cannot Load ELF Image\n"); + + post_code(0xff); + } + return 0; + +} +#endif +int elfboot_mem(struct lb_memory *mem, void *where, int size) +{ + Elf_ehdr *ehdr; + unsigned char *header = where; + int header_offset; + int i, result; + + result = 0; + printk(BIOS_INFO, "\n"); + printk(BIOS_INFO, "Elfboot\n"); + post_code(0xf8); + + /* Scan for an elf header */ + header_offset = -1; + for(i = 0; i < ELF_HEAD_SIZE - (sizeof(Elf_ehdr) + sizeof(Elf_phdr)); i+=16) { + ehdr = (Elf_ehdr *)(&header[i]); + if (memcmp(ehdr->e_ident, ELFMAG, 4) != 0) { + printk(BIOS_SPEW, "NO header at %d\n", i); + continue; + } + printk(BIOS_DEBUG, "Found ELF candidate at offset %d\n", i); + /* Sanity check the elf header */ + if ((ehdr->e_type == ET_EXEC) && + elf_check_arch(ehdr) && + (ehdr->e_ident[EI_VERSION] == EV_CURRENT) && + (ehdr->e_version == EV_CURRENT) && + (ehdr->e_ehsize == sizeof(Elf_ehdr)) && + (ehdr->e_phentsize = sizeof(Elf_phdr)) && + (ehdr->e_phoff < (ELF_HEAD_SIZE - i)) && + ((ehdr->e_phoff + (ehdr->e_phentsize * ehdr->e_phnum)) <= + (ELF_HEAD_SIZE - i))) { + header_offset = i; + break; + } + ehdr = 0; + } + printk(BIOS_SPEW, "header_offset is %d\n", header_offset); + if (header_offset == -1) { + goto out; + } + + printk(BIOS_SPEW, "Try to load at offset 0x%x\n", header_offset); + result = elfload(mem, + header + header_offset , ELF_HEAD_SIZE - header_offset); + out: + if (!result) { + + printk(BIOS_ERR, "Cannot Load ELF Image\n"); + + post_code(0xff); + } + return 0; +}