mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
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 <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@108 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
parent
39a8f1f159
commit
327a4432fe
5 changed files with 266 additions and 15 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
253
lib/newelfboot.c
Normal file
253
lib/newelfboot.c
Normal file
|
@ -0,0 +1,253 @@
|
|||
#include <console/console.h>
|
||||
//#include <part/fallback_boot.h>
|
||||
#include <elf.h>
|
||||
#include <elf_boot.h>
|
||||
#include <linuxbios_tables.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Add table
Reference in a new issue