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; +}