Files
openbios/packages/elf-loader.c

100 lines
2.1 KiB
C
Raw Normal View History

/*
*
* <elf-loader.c>
*
* ELF file loader
*
* Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
*
* Some parts Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2
*
*/
#include "config.h"
#include "libopenbios/bindings.h"
#include "packages.h"
#include "libopenbios/ofmem.h"
#include "arch/common/elf.h"
#include "asm/elf.h"
/* TODO: manage ELF notes section */
//#define DEBUG_ELF
#ifdef DEBUG_ELF
#define DPRINTF(fmt, args...) \
do { printk("%s: " fmt, __func__ , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) \
do { } while (0)
#endif
DECLARE_NODE(elf_loader, INSTALL_OPEN, 0, "+/packages/elf-loader" );
#ifdef CONFIG_PPC
extern void flush_icache_range( char *start, char *stop );
#endif
static void
elf_loader_init_program( void *dummy )
{
char *base;
int i;
Elf_ehdr *ehdr;
Elf_phdr *phdr;
size_t size;
char *addr;
cell tmp;
feval("0 state-valid !");
feval("load-base");
base = (char*)POP();
ehdr = (Elf_ehdr *)base;
phdr = (Elf_phdr *)(base + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++) {
DPRINTF("filesz: %08lX memsz: %08lX p_offset: %08lX "
"p_vaddr %08lX\n",
(ulong)phdr[i].p_filesz, (ulong)phdr[i].p_memsz,
(ulong)phdr[i].p_offset, (ulong)phdr[i].p_vaddr );
size = MIN(phdr[i].p_filesz, phdr[i].p_memsz);
if (!size)
continue;
#if 0
if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) {
printk("Claim failed!\n");
return;
}
#endif
/* Workaround for archs where sizeof(int) != pointer size */
tmp = phdr[i].p_vaddr;
addr = (char *)tmp;
memcpy(addr, base + phdr[i].p_offset, size);
#ifdef CONFIG_PPC
flush_icache_range( addr, addr + size );
#endif
}
/* FIXME: should initialize saved-program-state. */
PUSH(ehdr->e_entry);
feval("elf-entry !");
feval("-1 state-valid !");
}
NODE_METHODS( elf_loader ) = {
{ "init-program", elf_loader_init_program },
};
void elf_loader_init( void )
{
REGISTER_NODE( elf_loader );
}