Removed old elfloader.c and replaced with the current code (previously in elfloader-tmp.c)

This commit is contained in:
adamdunkels 2006-12-18 11:55:42 +00:00
parent 5d3baef0d2
commit 70170b65b6

View File

@ -1,77 +1,61 @@
/* /*
* Copyright (c) 2005, Swedish Institute of Computer Science * Copyright (c) 2005, Swedish Institute of Computer Science
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors * 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* @(#)$Id: elfloader.c,v 1.1 2006/06/17 22:41:18 adamdunkels Exp $ * @(#)$Id: elfloader.c,v 1.2 2006/12/18 11:55:42 adamdunkels Exp $
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/unistd.h>
#include "contiki.h" #include "contiki.h"
#include "loader/elfloader.h" #include "loader/elfloader-tmp.h"
#include "loader/elfloader-arch.h"
#include "cfs/cfs.h"
#include "loader/symtab.h" #include "loader/symtab.h"
#include "lib/malloc.h" #include <stddef.h>
#include "dev/rom.h" #include <string.h>
#include "dev/xmem.h" #include <stdio.h>
#if 0 #if 0
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__)
#else #else
#define PRINTF(...) do {} while (0) #define PRINTF(...) do {} while (0)
#endif #endif
#define IMAX(a, b) (((a) > (b)) ? (a) : (b))
static char *datamemory;
#define TEXTADDRESS \
(((uintptr_t)&_etext + (uintptr_t)&_edata - (uintptr_t)&__data_start \
+ ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE - 1))
#define EI_NIDENT 16 #define EI_NIDENT 16
typedef unsigned long elf32_word;
typedef signed long elf32_sword;
typedef unsigned short elf32_half;
typedef unsigned long elf32_off;
typedef unsigned long elf32_addr;
struct elf32_ehdr { struct elf32_ehdr {
unsigned char e_ident[EI_NIDENT]; /* ident bytes */ unsigned char e_ident[EI_NIDENT]; /* ident bytes */
elf32_half e_type; /* file type */ elf32_half e_type; /* file type */
elf32_half e_machine; /* target machine */ elf32_half e_machine; /* target machine */
elf32_word e_version; /* file version */ elf32_word e_version; /* file version */
elf32_addr e_entry; /* start address */ elf32_addr e_entry; /* start address */
@ -129,12 +113,6 @@ struct elf32_rel {
elf32_word r_info; /* Relocation type and symbol index. */ elf32_word r_info; /* Relocation type and symbol index. */
}; };
struct elf32_rela {
elf32_addr r_offset; /* Location to be relocated. */
elf32_word r_info; /* Relocation type and symbol index. */
elf32_sword r_addend; /* Addend. */
};
struct elf32_sym { struct elf32_sym {
elf32_word st_name; /* String table index of name. */ elf32_word st_name; /* String table index of name. */
elf32_addr st_value; /* Symbol value. */ elf32_addr st_value; /* Symbol value. */
@ -149,46 +127,119 @@ struct elf32_sym {
struct relevant_section { struct relevant_section {
unsigned char number; unsigned char number;
//off_t offset; unsigned int offset;
char *address; char *address;
}; };
char elfloader_unknown[30]; /* Name that caused link error. */ char elfloader_unknown[30]; /* Name that caused link error. */
struct process **elfloader_autostart_processes;
static struct relevant_section bss, data, text; static struct relevant_section bss, data, text;
/*static unsigned char bss_sectionno, data_sectionno, text_sectionno;*/ const static unsigned char elf_magic_header[] =
static const unsigned char elf_magic_header[] =
{0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */ {0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
0x01, /* Only 32-bit objects. */ 0x01, /* Only 32-bit objects. */
0x01, /* Only LSB data. */ 0x01, /* Only LSB data. */
0x01, /* Only ELF version 1. */ 0x01, /* Only ELF version 1. */
}; };
/*---------------------------------------------------------------------------*/
static void
seek_read(int fd, unsigned int offset, char *buf, int len)
{
cfs_seek(fd, offset);
cfs_read(fd, buf, len);
}
/*---------------------------------------------------------------------------*/
/*
static void
seek_write(int fd, unsigned int offset, char *buf, int len)
{
cfs_seek(fd, offset);
cfs_write(fd, buf, len);
}
*/
/*---------------------------------------------------------------------------*/
static void *
find_local_symbol(int fd, const char *symbol,
unsigned int symtab, unsigned short symtabsize,
unsigned int strtab)
{
struct elf32_sym s;
unsigned int a;
char name[30];
struct relevant_section *sect;
for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
seek_read(fd, a, (char *)&s, sizeof(s));
if(s.st_name != 0) {
seek_read(fd, strtab + s.st_name, name, sizeof(name));
if(strcmp(name, symbol) == 0) {
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == text.number) {
sect = &text;
} else {
return NULL;
}
return &(sect->address[s.st_value]);
}
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
relocate_section(off_t section, unsigned short size, relocate_section(int fd,
off_t sectionaddr, unsigned int section, unsigned short size,
off_t strs, unsigned int sectionaddr,
off_t strtab, unsigned int strs,
off_t symtab, unsigned int strtab,
char *mem) unsigned int symtab, unsigned short symtabsize)
{ {
struct elf32_rela rela; struct elf32_rela rela;
struct elf32_sym s; struct elf32_sym s;
off_t a; unsigned int a;
char name[30]; char name[30];
char *addr; char *addr;
struct relevant_section *sect; struct relevant_section *sect;
for(a = section; a < section + size; a += sizeof(struct elf32_rela)) { for(a = section; a < section + size; a += sizeof(struct elf32_rela)) {
xmem_pread(&rela, sizeof(rela), a); seek_read(fd, a, (char *)&rela, sizeof(rela));
xmem_pread(&s, sizeof(s), seek_read(fd,
symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)); symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
if(s.st_name == 0) { /* Local symbol (static) */ (char *)&s, sizeof(s));
if(s.st_shndx == bss.number) { if(s.st_name != 0) {
seek_read(fd, strtab + s.st_name, name, sizeof(name));
PRINTF("name: %s\n", name);
addr = (char *)symtab_lookup(name);
/* ADDED */
if(addr == NULL) {
PRINTF("name not found in global: %s\n", name);
addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
PRINTF("found address %p\n", addr);
}
if(addr == NULL) {
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == text.number) {
sect = &text;
} else {
PRINTF("elfloader unknown name: '%30s'\n", name);
memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
return ELFLOADER_SYMBOL_NOT_FOUND;
}
addr = sect->address;
}
} else {
if(s.st_shndx == bss.number) {
sect = &bss; sect = &bss;
} else if(s.st_shndx == data.number) { } else if(s.st_shndx == data.number) {
sect = &data; sect = &data;
@ -197,77 +248,70 @@ relocate_section(off_t section, unsigned short size,
} else { } else {
return ELFLOADER_SEGMENT_NOT_FOUND; return ELFLOADER_SEGMENT_NOT_FOUND;
} }
addr = sect->address + rela.r_addend;
} else { addr = sect->address;
xmem_pread(name, sizeof(name), strtab + s.st_name);
addr = (char *)symtab_lookup(name);
if(addr != NULL) { /* Global symbol */
addr += rela.r_addend;
} else { /* Exported symbol */
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == text.number) {
sect = &text;
} else {
PRINTF("elfloader unkown name: '%30s'\n", name);
memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
return ELFLOADER_SYMBOL_NOT_FOUND;
}
addr = sect->address + s.st_value + rela.r_addend;
}
} }
memcpy(&mem[rela.r_offset], &addr, 2); /* Write reloc */
elfloader_arch_relocate(fd, sectionaddr, &rela, addr);
} }
return ELFLOADER_OK; return ELFLOADER_OK;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
typedef void (*PFV)(void); static void *
find_program_processes(int fd,
struct process *elfloader_loaded_process; unsigned int symtab, unsigned short size,
void (*elfloader_fini)(void); unsigned int strtab)
static PFV
find_init_and_fini(off_t symtab, unsigned short size, off_t strtab)
{ {
struct elf32_sym s; struct elf32_sym s;
off_t a; unsigned int a;
char name[30]; char name[30];
void (*elfloader_init)(void);
elfloader_init = NULL;
for(a = symtab; a < symtab + size; a += sizeof(s)) { for(a = symtab; a < symtab + size; a += sizeof(s)) {
xmem_pread(&s, sizeof(s), a); seek_read(fd, a, (char *)&s, sizeof(s));
if(s.st_name != 0) { if(s.st_name != 0) {
xmem_pread(name, sizeof(name), strtab + s.st_name); seek_read(fd, strtab + s.st_name, name, sizeof(name));
if(strcmp(name, "process_load") == 0) { if(strcmp(name, "autostart_processes") == 0) {
elfloader_loaded_process = return &data.address[s.st_value];
*(struct process **)&data.address[s.st_value];
} else if (strcmp(name, "_init") == 0) {
/* XXX Check segment == text. */
elfloader_init = (PFV)&text.address[s.st_value];
} else if (strcmp(name, "_fini") == 0) {
/* XXX Check segment == text. */
elfloader_fini = (PFV)&text.address[s.st_value];
} }
} }
} }
return elfloader_init; return NULL;
/* return find_local_symbol(fd, "autostart_processes", symtab, size, strtab); */
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
elfloader_init(void)
{
elfloader_autostart_processes = NULL;
}
/*---------------------------------------------------------------------------*/
#if 0
static void
print_chars(unsigned char *ptr, int num)
{
int i;
for(i = 0; i < num; ++i) {
PRINTF("%d", ptr[i]);
if(i == num - 1) {
PRINTF("\n");
} else {
PRINTF(", ");
}
}
}
#endif /* 0 */
/*---------------------------------------------------------------------------*/
int int
elfloader_load(off_t eepromaddr) elfloader_load(int fd)
{ {
struct elf32_ehdr ehdr; struct elf32_ehdr ehdr;
struct elf32_shdr shdr; struct elf32_shdr shdr;
struct elf32_shdr strtable; struct elf32_shdr strtable;
off_t strs; unsigned int strs;
off_t shdrptr; unsigned int shdrptr;
off_t nameptr; unsigned int nameptr;
char name[12]; char name[12];
int i; int i;
@ -279,35 +323,38 @@ elfloader_load(off_t eepromaddr)
unsigned short strtaboff = 0, strtabsize; unsigned short strtaboff = 0, strtabsize;
unsigned short bsssize = 0; unsigned short bsssize = 0;
struct process **process;
int ret; int ret;
void (*elfloader_init)(void);
elfloader_unknown[0] = 0; elfloader_unknown[0] = 0;
/* The ELF header is located at the start of the buffer. */ /* The ELF header is located at the start of the buffer. */
xmem_pread(&ehdr, sizeof(ehdr), eepromaddr); seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
/* print_chars(ehdr.e_ident, sizeof(elf_magic_header));
print_chars(elf_magic_header, sizeof(elf_magic_header));*/
/* Make sure that we have a correct and compatible ELF header. */ /* Make sure that we have a correct and compatible ELF header. */
if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) { if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
PRINTF("ELF header problems\n");
return ELFLOADER_BAD_ELF_HEADER; return ELFLOADER_BAD_ELF_HEADER;
} }
/* Grab the section header. */ /* Grab the section header. */
shdrptr = eepromaddr + ehdr.e_shoff; shdrptr = ehdr.e_shoff;
xmem_pread(&shdr, sizeof(shdr), shdrptr); seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
/* Get the size and number of entries of the section header. */ /* Get the size and number of entries of the section header. */
shdrsize = ehdr.e_shentsize; shdrsize = ehdr.e_shentsize;
shdrnum = ehdr.e_shnum; shdrnum = ehdr.e_shnum;
/* The string table section: holds the names of the sections. */ /* The string table section: holds the names of the sections. */
xmem_pread(&strtable, sizeof(strtable), seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
eepromaddr + ehdr.e_shoff + shdrsize * ehdr.e_shstrndx); (char *)&strtable, sizeof(strtable));
/* Get a pointer to the actual table of strings. This table holds /* Get a pointer to the actual table of strings. This table holds
the names of the sections, not the names of other symbols in the the names of the sections, not the names of other symbols in the
file (these are in the sybtam section). */ file (these are in the sybtam section). */
strs = eepromaddr + strtable.sh_offset; strs = strtable.sh_offset;
/* Go through all sections and pick out the relevant ones. The /* Go through all sections and pick out the relevant ones. The
".text" segment holds the actual code from the ELF file, the ".text" segment holds the actual code from the ELF file, the
@ -332,24 +379,24 @@ elfloader_load(off_t eepromaddr)
bss.number = data.number = text.number = 0; bss.number = data.number = text.number = 0;
shdrptr = eepromaddr + ehdr.e_shoff; shdrptr = ehdr.e_shoff;
for(i = 0; i < shdrnum; ++i) { for(i = 0; i < shdrnum; ++i) {
xmem_pread(&shdr, sizeof(shdr), shdrptr); seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
/* The name of the section is contained in the strings table. */ /* The name of the section is contained in the strings table. */
nameptr = strs + shdr.sh_name; nameptr = strs + shdr.sh_name;
xmem_pread(name, sizeof(name), nameptr); seek_read(fd, nameptr, name, sizeof(name));
/* Match the name of the section with a predefined set of names /* Match the name of the section with a predefined set of names
(.text, .data, .bss, .rela.text, .rela.data, .symtab, and (.text, .data, .bss, .rela.text, .rela.data, .symtab, and
.strtab). */ .strtab). */
if(strncmp(name, ".text", 5) == 0) { if(strncmp(name, ".text", 5) == 0) {
textoff = shdr.sh_offset; textoff = shdr.sh_offset;
textsize = shdr.sh_size; textsize = shdr.sh_size;
text.number = i; text.number = i;
//text.offset = eepromaddr + textoff; text.offset = textoff;
} else if(strncmp(name, ".rela.text", 10) == 0) { } else if(strncmp(name, ".rela.text", 10) == 0) {
textrelaoff = shdr.sh_offset; textrelaoff = shdr.sh_offset;
textrelasize = shdr.sh_size; textrelasize = shdr.sh_size;
@ -357,7 +404,7 @@ elfloader_load(off_t eepromaddr)
dataoff = shdr.sh_offset; dataoff = shdr.sh_offset;
datasize = shdr.sh_size; datasize = shdr.sh_size;
data.number = i; data.number = i;
//data.offset = eepromaddr + dataoff; data.offset = dataoff;
} else if(strncmp(name, ".rela.data", 10) == 0) { } else if(strncmp(name, ".rela.data", 10) == 0) {
datarelaoff = shdr.sh_offset; datarelaoff = shdr.sh_offset;
datarelasize = shdr.sh_size; datarelasize = shdr.sh_size;
@ -370,16 +417,13 @@ elfloader_load(off_t eepromaddr)
} else if(strncmp(name, ".bss", 4) == 0) { } else if(strncmp(name, ".bss", 4) == 0) {
bsssize = shdr.sh_size; bsssize = shdr.sh_size;
bss.number = i; bss.number = i;
//bss.offset = 0; bss.offset = 0;
} else {
PRINTF("elfloader: unknown '%12s' %d\n", name, shdrsize);
} }
/* Move on to the next section header. */ /* Move on to the next section header. */
shdrptr += shdrsize; shdrptr += shdrsize;
} }
if(symtabsize == 0) { if(symtabsize == 0) {
return ELFLOADER_NO_SYMTAB; return ELFLOADER_NO_SYMTAB;
} }
@ -390,102 +434,60 @@ elfloader_load(off_t eepromaddr)
return ELFLOADER_NO_TEXT; return ELFLOADER_NO_TEXT;
} }
if(datamemory != NULL) { bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
free(datamemory); data.address = (char *)bss.address + bsssize;
} text.address = (char *)elfloader_arch_allocate_rom(textsize);
/* We are making semi-permanent allocations, first compact heap! */
malloc_compact(); /* If we have text segment relocations, we process them. */
datamemory = malloc(IMAX(textsize, datasize + bsssize)); PRINTF("elfloader: relocate text\n");
if(datamemory == NULL) {
return ELFLOADER_DATA_TO_LARGE; /* XXX or text to large */
}
bss.address = (char *)datamemory;
data.address = (char *)datamemory + bsssize;
text.address = (char *)TEXTADDRESS;
PRINTF("elfloader: copy text segment to RAM %p %p\n",
datamemory, datamemory + textsize);
xmem_pread(datamemory, textsize, eepromaddr + textoff);
if(textrelasize > 0) { if(textrelasize > 0) {
PRINTF("elfloader: relocate text in RAM\n"); ret = relocate_section(fd,
ret = relocate_section(eepromaddr + textrelaoff, textrelasize, textrelaoff, textrelasize,
eepromaddr + textoff, textoff,
strs, strs,
eepromaddr + strtaboff, strtaboff,
eepromaddr + symtaboff, symtaboff, symtabsize);
datamemory);
if(ret != ELFLOADER_OK) { if(ret != ELFLOADER_OK) {
return ret; return ret;
} }
} }
PRINTF("elfloader: copy text segment to ROM %p %p\n",
text.address, text.address + textsize);
rom_erase((textsize + ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE - 1),
(uintptr_t)text.address);
rom_pwrite(datamemory, textsize, (uintptr_t)text.address);
PRINTF("elfloader: copy data segment to RAM %p %p\n", /* If we have any data segment relocations, we process them too. */
data.address, data.address + datasize); PRINTF("elfloader: relocate data\n");
xmem_pread(data.address, datasize, eepromaddr + dataoff);
if(datarelasize > 0) { if(datarelasize > 0) {
PRINTF("elfloader: relocate data segment\n"); ret = relocate_section(fd,
ret = relocate_section(eepromaddr + datarelaoff, datarelasize, datarelaoff, datarelasize,
eepromaddr + dataoff, dataoff,
strs, strs,
eepromaddr + strtaboff, strtaboff,
eepromaddr + symtaboff, symtaboff, symtabsize);
data.address);
if(ret != ELFLOADER_OK) { if(ret != ELFLOADER_OK) {
PRINTF("elfloader: data failed\n");
return ret; return ret;
} }
} }
PRINTF("elfloader: zero bss %p %p\n", bss.address, bss.address + bsssize); /* Write text segment into flash and data segment into RAM. */
cfs_seek(fd, textoff);
elfloader_arch_write_text(fd, textsize, text.address);
memset(bss.address, 0, bsssize); memset(bss.address, 0, bsssize);
datamemory = realloc(datamemory, datasize + bsssize); seek_read(fd, dataoff, data.address, datasize);
if(datamemory != bss.address) {
free(bss.address);
return ELFLOADER_BSS_TO_LARGE; /* XXX realloc moved data */
}
/* Find _init, _fini, and loaded_process. */ PRINTF("elfloader: autostart search\n");
elfloader_loaded_process = NULL; process = find_local_symbol(fd, "autostart_processes", symtaboff, symtabsize, strtaboff);
elfloader_fini = NULL; if(process != NULL) {
elfloader_init = find_init_and_fini(eepromaddr + symtaboff, PRINTF("elfloader: autostart found\n");
symtabsize, elfloader_autostart_processes = process;
eepromaddr + strtaboff);
if(elfloader_init != NULL) {
PRINTF("init=%p fini=%p\n", elfloader_init, elfloader_fini);
(*elfloader_init)();
elfloader_loaded_process = NULL;
return ELFLOADER_OK;
}
if(elfloader_loaded_process != NULL) {
PRINTF("elfloader: launch program\n");
process_start(elfloader_loaded_process, NULL);
elfloader_fini = NULL;
return ELFLOADER_OK; return ELFLOADER_OK;
} else { } else {
PRINTF("elfloader: no autostart\n");
process = find_program_processes(fd, symtaboff, symtabsize, strtaboff);
if(process != NULL) {
PRINTF("elfloader: FOUND PRG\n");
}
return ELFLOADER_NO_STARTPOINT; return ELFLOADER_NO_STARTPOINT;
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
elfloader_unload(void)
{
if(elfloader_fini != NULL) {
(*elfloader_fini)();
elfloader_fini = NULL;
} else if(elfloader_loaded_process != NULL) {
process_exit(elfloader_loaded_process);
elfloader_loaded_process = NULL;
}
if(datamemory != NULL) {
free(datamemory);
datamemory = NULL;
}
}