Older ELF-loader code, may not work any longer
This commit is contained in:
parent
4a82069f15
commit
1658d6b42c
523
cpu/arm/at91sam7s/loader/codeprop-otf.c
Normal file
523
cpu/arm/at91sam7s/loader/codeprop-otf.c
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 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
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* 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
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* @(#)$Id: codeprop-otf.c,v 1.1 2009/07/11 14:18:50 ksb Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \addtogroup esb
|
||||||
|
* @{ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \file
|
||||||
|
* Code propagation and storage.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*
|
||||||
|
* This file implements a simple form of code propagation, which
|
||||||
|
* allows a binary program to be downloaded and propagated throughout
|
||||||
|
* a network of devices.
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
*
|
||||||
|
* Commands: load code, start code
|
||||||
|
* Point-to-point download over TCP
|
||||||
|
* Point-to-multipoint delivery over UDP broadcasts
|
||||||
|
* Versioning of code modules
|
||||||
|
*
|
||||||
|
* Procedure:
|
||||||
|
*
|
||||||
|
* 1. Receive code over TCP
|
||||||
|
* 2. Send code packets over UDP
|
||||||
|
*
|
||||||
|
* When a code packet is deemed to be missed, a NACK is sent. If a
|
||||||
|
* NACK is received, the sending restarts at the point in the
|
||||||
|
* binary where the NACK pointed to. (This is *not* very efficient,
|
||||||
|
* but simple to implement...)
|
||||||
|
*
|
||||||
|
* States:
|
||||||
|
*
|
||||||
|
* Receiving code header -> receiving code -> sending code
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "contiki-net.h"
|
||||||
|
#include "cfs/cfs.h"
|
||||||
|
#include "codeprop-otf.h"
|
||||||
|
#include "loader/elfloader-otf.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char *err_msgs[] =
|
||||||
|
{"OK\r\n", "Bad ELF header\r\n", "No symtab\r\n", "No strtab\r\n",
|
||||||
|
"No text\r\n", "Symbol not found\r\n", "Segment not found\r\n",
|
||||||
|
"No startpoint\r\n", "Unhandled relocation\r\n",
|
||||||
|
"Relocation out of range\r\n", "Relocations not sorted\r\n",
|
||||||
|
"Input error\r\n" , "Ouput error\r\n" };
|
||||||
|
|
||||||
|
#define CODEPROP_DATA_PORT 6510
|
||||||
|
|
||||||
|
/*static int random_rand(void) { return 1; }*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define PRINTF(x) printf x
|
||||||
|
#else
|
||||||
|
#define PRINTF(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define START_TIMEOUT 12 * CLOCK_SECOND
|
||||||
|
#define MISS_NACK_TIMEOUT (CLOCK_SECOND / 8) * (random_rand() % 8)
|
||||||
|
#define HIT_NACK_TIMEOUT (CLOCK_SECOND / 8) * (8 + random_rand() % 16)
|
||||||
|
#define NACK_REXMIT_TIMEOUT CLOCK_SECOND * (4 + random_rand() % 4)
|
||||||
|
|
||||||
|
#define WAITING_TIME CLOCK_SECOND * 10
|
||||||
|
|
||||||
|
#define NUM_SEND_DUPLICATES 2
|
||||||
|
|
||||||
|
#define UDPHEADERSIZE 8
|
||||||
|
#define UDPDATASIZE 32
|
||||||
|
|
||||||
|
struct codeprop_udphdr {
|
||||||
|
u16_t id;
|
||||||
|
u16_t type;
|
||||||
|
#define TYPE_DATA 0x0001
|
||||||
|
#define TYPE_NACK 0x0002
|
||||||
|
u16_t addr;
|
||||||
|
u16_t len;
|
||||||
|
u8_t data[UDPDATASIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct codeprop_tcphdr {
|
||||||
|
u16_t len;
|
||||||
|
u16_t pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void uipcall(void *state);
|
||||||
|
|
||||||
|
PROCESS(codeprop_process, "Code propagator");
|
||||||
|
|
||||||
|
struct codeprop_state {
|
||||||
|
u8_t state;
|
||||||
|
#define STATE_NONE 0
|
||||||
|
#define STATE_RECEIVING_TCPDATA 1
|
||||||
|
#define STATE_RECEIVING_UDPDATA 2
|
||||||
|
#define STATE_SENDING_UDPDATA 3
|
||||||
|
u16_t count;
|
||||||
|
u16_t addr;
|
||||||
|
u16_t len;
|
||||||
|
u16_t id;
|
||||||
|
struct etimer sendtimer;
|
||||||
|
struct timer nacktimer, timer, starttimer;
|
||||||
|
u8_t received;
|
||||||
|
u8_t send_counter;
|
||||||
|
struct pt tcpthread_pt;
|
||||||
|
struct pt udpthread_pt;
|
||||||
|
struct pt recv_udpthread_pt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int fd;
|
||||||
|
|
||||||
|
static struct uip_udp_conn *udp_conn;
|
||||||
|
|
||||||
|
static struct codeprop_state s;
|
||||||
|
|
||||||
|
void system_log(char *msg);
|
||||||
|
|
||||||
|
static clock_time_t send_time;
|
||||||
|
|
||||||
|
#define CONNECTION_TIMEOUT (30 * CLOCK_SECOND)
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
codeprop_set_rate(clock_time_t time)
|
||||||
|
{
|
||||||
|
send_time = time;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
PROCESS_THREAD(codeprop_process, ev, data)
|
||||||
|
{
|
||||||
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
|
elfloader_init();
|
||||||
|
|
||||||
|
s.id = 0/*random_rand()*/;
|
||||||
|
|
||||||
|
send_time = CLOCK_SECOND/4;
|
||||||
|
|
||||||
|
PT_INIT(&s.udpthread_pt);
|
||||||
|
PT_INIT(&s.recv_udpthread_pt);
|
||||||
|
|
||||||
|
tcp_listen(HTONS(CODEPROP_DATA_PORT));
|
||||||
|
|
||||||
|
udp_conn = udp_broadcast_new(HTONS(CODEPROP_DATA_PORT), NULL);
|
||||||
|
|
||||||
|
s.state = STATE_NONE;
|
||||||
|
s.received = 0;
|
||||||
|
s.addr = 0;
|
||||||
|
s.len = 0;
|
||||||
|
|
||||||
|
fd = cfs_open("codeprop-image", CFS_READ | CFS_WRITE);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
PROCESS_YIELD();
|
||||||
|
|
||||||
|
if(ev == tcpip_event) {
|
||||||
|
uipcall(data);
|
||||||
|
} else if(ev == PROCESS_EVENT_TIMER) {
|
||||||
|
tcpip_poll_udp(udp_conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_END();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static u16_t
|
||||||
|
send_udpdata(struct codeprop_udphdr *uh)
|
||||||
|
{
|
||||||
|
u16_t len;
|
||||||
|
|
||||||
|
uh->type = HTONS(TYPE_DATA);
|
||||||
|
uh->addr = htons(s.addr);
|
||||||
|
uh->id = htons(s.id);
|
||||||
|
|
||||||
|
if(s.len - s.addr > UDPDATASIZE) {
|
||||||
|
len = UDPDATASIZE;
|
||||||
|
} else {
|
||||||
|
len = s.len - s.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfs_seek(fd, s.addr, CFS_SEEK_SET);
|
||||||
|
cfs_read(fd, (char*)&uh->data[0], len);
|
||||||
|
/* eeprom_read(EEPROMFS_ADDR_CODEPROP + s.addr,
|
||||||
|
&uh->data[0], len);*/
|
||||||
|
|
||||||
|
uh->len = htons(s.len);
|
||||||
|
|
||||||
|
PRINTF(("codeprop: sending packet from address 0x%04x\n", s.addr));
|
||||||
|
uip_udp_send(len + UDPHEADERSIZE);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static
|
||||||
|
PT_THREAD(send_udpthread(struct pt *pt))
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct codeprop_udphdr *uh = (struct codeprop_udphdr *)uip_appdata;
|
||||||
|
|
||||||
|
|
||||||
|
PT_BEGIN(pt);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
PT_WAIT_UNTIL(pt, s.state == STATE_SENDING_UDPDATA);
|
||||||
|
|
||||||
|
for(s.addr = 0; s.addr < s.len; ) {
|
||||||
|
len = send_udpdata(uh);
|
||||||
|
s.addr += len;
|
||||||
|
|
||||||
|
etimer_set(&s.sendtimer, CLOCK_SECOND/4);
|
||||||
|
do {
|
||||||
|
PT_WAIT_UNTIL(pt, uip_newdata() || etimer_expired(&s.sendtimer));
|
||||||
|
|
||||||
|
if(uip_newdata()) {
|
||||||
|
if(uh->type == HTONS(TYPE_NACK)) {
|
||||||
|
PRINTF(("send_udpthread: got NACK for address 0x%x (now 0x%x)\n",
|
||||||
|
htons(uh->addr), s.addr));
|
||||||
|
/* Only accept a NACK if it points to a lower byte. */
|
||||||
|
if(htons(uh->addr) <= s.addr) {
|
||||||
|
/* beep();*/
|
||||||
|
s.addr = htons(uh->addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PT_YIELD(pt);
|
||||||
|
}
|
||||||
|
} while(!etimer_expired(&s.sendtimer));
|
||||||
|
}
|
||||||
|
|
||||||
|
s.state = STATE_NONE;
|
||||||
|
|
||||||
|
/* process_post(PROCESS_BROADCAST, codeprop_event_quit, (process_data_t)NULL); */
|
||||||
|
}
|
||||||
|
PT_END(pt);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
send_nack(struct codeprop_udphdr *uh, unsigned short addr)
|
||||||
|
{
|
||||||
|
uh->type = HTONS(TYPE_NACK);
|
||||||
|
uh->addr = htons(addr);
|
||||||
|
uip_udp_send(UDPHEADERSIZE);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static
|
||||||
|
PT_THREAD(recv_udpthread(struct pt *pt))
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
struct codeprop_udphdr *uh = (struct codeprop_udphdr *)uip_appdata;
|
||||||
|
|
||||||
|
/* if(uip_newdata()) {
|
||||||
|
PRINTF(("recv_udpthread: id %d uh->id %d\n", s.id, htons(uh->id)));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
PT_BEGIN(pt);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
PT_WAIT_UNTIL(pt, uip_newdata() &&
|
||||||
|
uh->type == HTONS(TYPE_DATA) &&
|
||||||
|
htons(uh->id) > s.id);
|
||||||
|
|
||||||
|
if(htons(uh->addr) != 0) {
|
||||||
|
s.addr = 0;
|
||||||
|
send_nack(uh, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(htons(uh->addr) != 0);
|
||||||
|
|
||||||
|
/* leds_on(LEDS_YELLOW);
|
||||||
|
beep_down(10000);*/
|
||||||
|
|
||||||
|
s.addr = 0;
|
||||||
|
s.id = htons(uh->id);
|
||||||
|
s.len = htons(uh->len);
|
||||||
|
|
||||||
|
timer_set(&s.timer, CONNECTION_TIMEOUT);
|
||||||
|
/* process_post(PROCESS_BROADCAST, codeprop_event_quit, (process_data_t)NULL); */
|
||||||
|
|
||||||
|
while(s.addr < s.len) {
|
||||||
|
|
||||||
|
if(htons(uh->addr) == s.addr) {
|
||||||
|
/* leds_blink();*/
|
||||||
|
len = uip_datalen() - UDPHEADERSIZE;
|
||||||
|
if(len > 0) {
|
||||||
|
/* eeprom_write(EEPROMFS_ADDR_CODEPROP + s.addr,
|
||||||
|
&uh->data[0], len);*/
|
||||||
|
cfs_seek(fd, s.addr, CFS_SEEK_SET);
|
||||||
|
cfs_write(fd, (char*)&uh->data[0], len);
|
||||||
|
|
||||||
|
/* beep();*/
|
||||||
|
PRINTF(("Saved %d bytes at address %d, %d bytes left\n",
|
||||||
|
uip_datalen() - UDPHEADERSIZE, s.addr,
|
||||||
|
s.len - s.addr));
|
||||||
|
|
||||||
|
s.addr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(htons(uh->addr) > s.addr) {
|
||||||
|
PRINTF(("sending nack since 0x%x != 0x%x\n", htons(uh->addr), s.addr));
|
||||||
|
send_nack(uh, s.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s.addr < s.len) {
|
||||||
|
|
||||||
|
/* timer_set(&s.nacktimer, NACK_TIMEOUT);*/
|
||||||
|
|
||||||
|
do {
|
||||||
|
timer_set(&s.nacktimer, HIT_NACK_TIMEOUT);
|
||||||
|
PT_YIELD_UNTIL(pt, timer_expired(&s.nacktimer) ||
|
||||||
|
(uip_newdata() &&
|
||||||
|
uh->type == HTONS(TYPE_DATA) &&
|
||||||
|
htons(uh->id) == s.id));
|
||||||
|
if(timer_expired(&s.nacktimer)) {
|
||||||
|
send_nack(uh, s.addr);
|
||||||
|
}
|
||||||
|
} while(timer_expired(&s.nacktimer));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* leds_off(LEDS_YELLOW);
|
||||||
|
beep_quick(2);*/
|
||||||
|
/* printf("Received entire bunary over udr\n");*/
|
||||||
|
codeprop_start_program();
|
||||||
|
PT_EXIT(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
PT_END(pt);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define CODEPROP_TCPHDR_SIZE sizeof(struct codeprop_tcphdr)
|
||||||
|
|
||||||
|
static
|
||||||
|
PT_THREAD(recv_tcpthread(struct pt *pt))
|
||||||
|
{
|
||||||
|
struct codeprop_tcphdr *th;
|
||||||
|
int datalen = uip_datalen();
|
||||||
|
PT_BEGIN(pt);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
PT_WAIT_UNTIL(pt, uip_connected());
|
||||||
|
|
||||||
|
codeprop_exit_program();
|
||||||
|
|
||||||
|
s.state = STATE_RECEIVING_TCPDATA;
|
||||||
|
|
||||||
|
s.addr = 0;
|
||||||
|
s.count = 0;
|
||||||
|
|
||||||
|
/* Read the header. */
|
||||||
|
PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0);
|
||||||
|
|
||||||
|
if(uip_datalen() < CODEPROP_TCPHDR_SIZE) {
|
||||||
|
PRINTF(("codeprop: header not found in first tcp segment\n"));
|
||||||
|
uip_abort();
|
||||||
|
}
|
||||||
|
th = (struct codeprop_tcphdr *)uip_appdata;
|
||||||
|
s.len = htons(th->len);
|
||||||
|
s.addr = 0;
|
||||||
|
uip_appdata += CODEPROP_TCPHDR_SIZE;
|
||||||
|
datalen -= CODEPROP_TCPHDR_SIZE;
|
||||||
|
|
||||||
|
/* Read the rest of the data. */
|
||||||
|
do {
|
||||||
|
if(datalen > 0) {
|
||||||
|
/* printf("Got %d bytes\n", datalen); */
|
||||||
|
|
||||||
|
if (cfs_seek(fd, s.addr, CFS_SEEK_SET) != s.addr) {
|
||||||
|
PRINTF(("codeprop: seek in buffer file failed\n"));
|
||||||
|
uip_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfs_write(fd, uip_appdata, datalen) != datalen) {
|
||||||
|
PRINTF(("codeprop: write to buffer file failed\n"));
|
||||||
|
uip_abort();
|
||||||
|
}
|
||||||
|
s.addr += datalen;
|
||||||
|
}
|
||||||
|
if(s.addr < s.len) {
|
||||||
|
PT_YIELD_UNTIL(pt, uip_newdata());
|
||||||
|
}
|
||||||
|
} while(s.addr < s.len);
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
{
|
||||||
|
static int err;
|
||||||
|
|
||||||
|
err = codeprop_start_program();
|
||||||
|
|
||||||
|
/* Print out the "OK"/error message. */
|
||||||
|
do {
|
||||||
|
if (err >= 0 && err < sizeof(err_msgs)/sizeof(char*)) {
|
||||||
|
uip_send(err_msgs[err], strlen(err_msgs[err]));
|
||||||
|
} else {
|
||||||
|
uip_send("Unknown error\r\n", 15);
|
||||||
|
}
|
||||||
|
PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed());
|
||||||
|
} while(uip_rexmit());
|
||||||
|
|
||||||
|
/* Close the connection. */
|
||||||
|
uip_close();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
++s.id;
|
||||||
|
s.state = STATE_SENDING_UDPDATA;
|
||||||
|
tcpip_poll_udp(udp_conn);
|
||||||
|
|
||||||
|
PT_WAIT_UNTIL(pt, s.state != STATE_SENDING_UDPDATA);
|
||||||
|
/* printf("recv_tcpthread: unblocked\n");*/
|
||||||
|
}
|
||||||
|
|
||||||
|
PT_END(pt);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
codeprop_start_broadcast(unsigned int len)
|
||||||
|
{
|
||||||
|
s.addr = 0;
|
||||||
|
s.len = len;
|
||||||
|
++s.id;
|
||||||
|
s.state = STATE_SENDING_UDPDATA;
|
||||||
|
tcpip_poll_udp(udp_conn);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
codeprop_exit_program(void)
|
||||||
|
{
|
||||||
|
if(elfloader_autostart_processes != NULL) {
|
||||||
|
autostart_exit(elfloader_autostart_processes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
codeprop_start_program(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
codeprop_exit_program();
|
||||||
|
|
||||||
|
err = elfloader_load(fd, codeprop_output);
|
||||||
|
if(err == ELFLOADER_OK) {
|
||||||
|
PRINTF(("codeprop: starting %s\n",
|
||||||
|
elfloader_autostart_processes[0]->name));
|
||||||
|
autostart_start(elfloader_autostart_processes);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
uipcall(void *state)
|
||||||
|
{
|
||||||
|
if(uip_udpconnection()) {
|
||||||
|
recv_udpthread(&s.recv_udpthread_pt);
|
||||||
|
send_udpthread(&s.udpthread_pt);
|
||||||
|
} else {
|
||||||
|
if(uip_conn->lport == HTONS(CODEPROP_DATA_PORT)) {
|
||||||
|
if(uip_connected()) {
|
||||||
|
|
||||||
|
if(state == NULL) {
|
||||||
|
s.addr = 0;
|
||||||
|
s.count = 0;
|
||||||
|
PT_INIT(&s.tcpthread_pt);
|
||||||
|
process_poll(&codeprop_process);
|
||||||
|
tcp_markconn(uip_conn, &s);
|
||||||
|
/* process_post(PROCESS_BROADCAST, codeprop_event_quit, */
|
||||||
|
/* (process_data_t)NULL); */
|
||||||
|
} else {
|
||||||
|
PRINTF(("codeprop: uip_connected() and state != NULL\n"));
|
||||||
|
uip_abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recv_tcpthread(&s.tcpthread_pt);
|
||||||
|
|
||||||
|
|
||||||
|
if(uip_closed() || uip_aborted() || uip_timedout()) {
|
||||||
|
PRINTF(("codeprop: connection down\n"));
|
||||||
|
tcp_markconn(uip_conn, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
/** @} */
|
52
cpu/arm/at91sam7s/loader/codeprop-otf.h
Normal file
52
cpu/arm/at91sam7s/loader/codeprop-otf.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 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
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* 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
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* @(#)$Id: codeprop-otf.h,v 1.1 2009/07/11 14:18:50 ksb Exp $
|
||||||
|
*/
|
||||||
|
#ifndef __CODEPROP_H__
|
||||||
|
#define __CODEPROP_H__
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
|
|
||||||
|
#define CODEPROP_DATA_PORT 6510
|
||||||
|
|
||||||
|
PROCESS_NAME(codeprop_process);
|
||||||
|
|
||||||
|
void codeprop_set_rate(clock_time_t time);
|
||||||
|
void codeprop_start_broadcast(unsigned int len);
|
||||||
|
void codeprop_exit_program(void);
|
||||||
|
int codeprop_start_program(void);
|
||||||
|
|
||||||
|
/* Segment writing object */
|
||||||
|
extern struct elfloader_output *codeprop_output;
|
||||||
|
|
||||||
|
extern char *codeprop_filesystem;
|
||||||
|
|
||||||
|
#endif /* __CODEPROP_H__ */
|
101
cpu/arm/at91sam7s/loader/elfloader-arch-otf.h
Normal file
101
cpu/arm/at91sam7s/loader/elfloader-arch-otf.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||||
|
* Copyright (c) 2007, Simon Berg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 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
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* 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
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* @(#)$Id: elfloader-arch-otf.h,v 1.1 2009/07/11 14:18:50 ksb Exp $
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \addtogroup elfloader
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup elfloaderarch Architecture specific functionality for the ELF loader.
|
||||||
|
*
|
||||||
|
* The architecture specific functionality for the Contiki ELF loader
|
||||||
|
* has to be implemented for each processor type Contiki runs on.
|
||||||
|
*
|
||||||
|
* Since the ELF format is slightly different for different processor
|
||||||
|
* types, the Contiki ELF loader is divided into two parts: the
|
||||||
|
* generic ELF loader module (\ref elfloader) and the architecture
|
||||||
|
* specific part (this module). The architecture specific part deals
|
||||||
|
* with memory allocation, code and data relocation, and writing the
|
||||||
|
* relocated ELF code into program memory.
|
||||||
|
*
|
||||||
|
* To port the Contiki ELF loader to a new processor type, this module
|
||||||
|
* has to be implemented for the new processor type.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Header file for the architecture specific parts of the Contiki ELF loader.
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ELFLOADER_ARCH_H__
|
||||||
|
#define __ELFLOADER_ARCH_H__
|
||||||
|
|
||||||
|
#include "elfloader-otf.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Perform a relocation.
|
||||||
|
* \param output The output object for the segment.
|
||||||
|
* \param sectionoffset The file offset at which the relocation can be found.
|
||||||
|
* \param sectionaddr The section start address (absolute runtime).
|
||||||
|
* \param rela A pointer to an ELF32 rela structure (struct elf32_rela).
|
||||||
|
* \param addr The relocated address.
|
||||||
|
*
|
||||||
|
* This function is called from the Contiki ELF loader to
|
||||||
|
* perform a relocation on a piece of code or data. The
|
||||||
|
* relocated address is calculated by the Contiki ELF
|
||||||
|
* loader, based on information in the ELF file, and it is
|
||||||
|
* the responsibility of this function to patch the
|
||||||
|
* executable code. The Contiki ELF loader passes a
|
||||||
|
* pointer to an ELF32 rela structure (struct elf32_rela)
|
||||||
|
* that contains information about how to patch the
|
||||||
|
* code. This information is different from processor to
|
||||||
|
* processor.
|
||||||
|
*/
|
||||||
|
int elfloader_arch_relocate(int input_fd,
|
||||||
|
struct elfloader_output *output,
|
||||||
|
unsigned int sectionoffset,
|
||||||
|
char *sectionaddr,
|
||||||
|
struct elf32_rela *rela, char *addr);
|
||||||
|
|
||||||
|
#endif /* __ELFLOADER_ARCH_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
/** @} */
|
680
cpu/arm/at91sam7s/loader/elfloader-otf.c
Normal file
680
cpu/arm/at91sam7s/loader/elfloader-otf.c
Normal file
|
@ -0,0 +1,680 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||||
|
* Copyright (c) 2007, Simon Berg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 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
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* 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
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
* @(#)$Id: elfloader-otf.c,v 1.1 2009/07/11 14:18:50 ksb Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
|
|
||||||
|
#include "loader/elfloader-otf.h"
|
||||||
|
#include "loader/elfloader-arch-otf.h"
|
||||||
|
|
||||||
|
#include "cfs/cfs.h"
|
||||||
|
#include "loader/symtab.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <stdio.h>
|
||||||
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define PRINTF(...) do {} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
|
||||||
|
struct elf32_ehdr {
|
||||||
|
unsigned char e_ident[EI_NIDENT]; /* ident bytes */
|
||||||
|
elf32_half e_type; /* file type */
|
||||||
|
elf32_half e_machine; /* target machine */
|
||||||
|
elf32_word e_version; /* file version */
|
||||||
|
elf32_addr e_entry; /* start address */
|
||||||
|
elf32_off e_phoff; /* phdr file offset */
|
||||||
|
elf32_off e_shoff; /* shdr file offset */
|
||||||
|
elf32_word e_flags; /* file flags */
|
||||||
|
elf32_half e_ehsize; /* sizeof ehdr */
|
||||||
|
elf32_half e_phentsize; /* sizeof phdr */
|
||||||
|
elf32_half e_phnum; /* number phdrs */
|
||||||
|
elf32_half e_shentsize; /* sizeof shdr */
|
||||||
|
elf32_half e_shnum; /* number shdrs */
|
||||||
|
elf32_half e_shstrndx; /* shdr string index */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Values for e_type. */
|
||||||
|
#define ET_NONE 0 /* Unknown type. */
|
||||||
|
#define ET_REL 1 /* Relocatable. */
|
||||||
|
#define ET_EXEC 2 /* Executable. */
|
||||||
|
#define ET_DYN 3 /* Shared object. */
|
||||||
|
#define ET_CORE 4 /* Core file. */
|
||||||
|
|
||||||
|
struct elf32_shdr {
|
||||||
|
elf32_word sh_name; /* section name */
|
||||||
|
elf32_word sh_type; /* SHT_... */
|
||||||
|
elf32_word sh_flags; /* SHF_... */
|
||||||
|
elf32_addr sh_addr; /* virtual address */
|
||||||
|
elf32_off sh_offset; /* file offset */
|
||||||
|
elf32_word sh_size; /* section size */
|
||||||
|
elf32_word sh_link; /* misc info */
|
||||||
|
elf32_word sh_info; /* misc info */
|
||||||
|
elf32_word sh_addralign; /* memory alignment */
|
||||||
|
elf32_word sh_entsize; /* entry size if table */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* sh_type */
|
||||||
|
#define SHT_NULL 0 /* inactive */
|
||||||
|
#define SHT_PROGBITS 1 /* program defined information */
|
||||||
|
#define SHT_SYMTAB 2 /* symbol table section */
|
||||||
|
#define SHT_STRTAB 3 /* string table section */
|
||||||
|
#define SHT_RELA 4 /* relocation section with addends*/
|
||||||
|
#define SHT_HASH 5 /* symbol hash table section */
|
||||||
|
#define SHT_DYNAMIC 6 /* dynamic section */
|
||||||
|
#define SHT_NOTE 7 /* note section */
|
||||||
|
#define SHT_NOBITS 8 /* no space section */
|
||||||
|
#define SHT_REL 9 /* relation section without addends */
|
||||||
|
#define SHT_SHLIB 10 /* reserved - purpose unknown */
|
||||||
|
#define SHT_DYNSYM 11 /* dynamic symbol table section */
|
||||||
|
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
|
||||||
|
#define SHT_HIPROC 0x7fffffff /* specific section header types */
|
||||||
|
#define SHT_LOUSER 0x80000000 /* reserved range for application */
|
||||||
|
#define SHT_HIUSER 0xffffffff /* specific indexes */
|
||||||
|
|
||||||
|
struct elf32_rel {
|
||||||
|
elf32_addr r_offset; /* Location to be relocated. */
|
||||||
|
elf32_word r_info; /* Relocation type and symbol index. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct elf32_sym {
|
||||||
|
elf32_word st_name; /* String table index of name. */
|
||||||
|
elf32_addr st_value; /* Symbol value. */
|
||||||
|
elf32_word st_size; /* Size of associated object. */
|
||||||
|
unsigned char st_info; /* Type and binding information. */
|
||||||
|
unsigned char st_other; /* Reserved (not used). */
|
||||||
|
elf32_half st_shndx; /* Section index of symbol. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ELF32_R_SYM(info) ((info) >> 8)
|
||||||
|
#define ELF32_R_TYPE(info) ((unsigned char)(info))
|
||||||
|
|
||||||
|
struct relevant_section {
|
||||||
|
unsigned char number;
|
||||||
|
unsigned int offset;
|
||||||
|
char *address;
|
||||||
|
};
|
||||||
|
|
||||||
|
char elfloader_unknown[30]; /* Name that caused link error. */
|
||||||
|
|
||||||
|
struct process **elfloader_autostart_processes;
|
||||||
|
|
||||||
|
static struct relevant_section bss, data, rodata, text;
|
||||||
|
|
||||||
|
const static unsigned char elf_magic_header[] =
|
||||||
|
{0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
|
||||||
|
0x01, /* Only 32-bit objects. */
|
||||||
|
0x01, /* Only LSB data. */
|
||||||
|
0x01, /* Only ELF version 1. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Copy data from the elf file to a segment */
|
||||||
|
static int
|
||||||
|
copy_segment_data(int input_fd, unsigned int offset,
|
||||||
|
struct elfloader_output *output, unsigned int len)
|
||||||
|
{
|
||||||
|
char buffer[16];
|
||||||
|
int res;
|
||||||
|
if (cfs_seek(input_fd, offset, CFS_SEEK_SET) != offset) return ELFLOADER_INPUT_ERROR;
|
||||||
|
while(len > sizeof(buffer)) {
|
||||||
|
res = cfs_read(input_fd, buffer, sizeof(buffer));
|
||||||
|
if (res != sizeof(buffer)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
res = elfloader_output_write_segment(output, buffer, sizeof(buffer));
|
||||||
|
if (res != sizeof(buffer)) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
len -= sizeof(buffer);
|
||||||
|
}
|
||||||
|
res = cfs_read(input_fd, buffer, len);
|
||||||
|
if (res != len) return ELFLOADER_INPUT_ERROR;
|
||||||
|
res = elfloader_output_write_segment(output, buffer, len);
|
||||||
|
if (res != len) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
return ELFLOADER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
seek_read(int fd, unsigned int offset, char *buf, int len)
|
||||||
|
{
|
||||||
|
if (cfs_seek(fd, offset, CFS_SEEK_SET) != offset) return -1;
|
||||||
|
return cfs_read(fd, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
find_local_symbol(int input_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;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
|
||||||
|
ret = seek_read(input_fd, a, (char *)&s, sizeof(s));
|
||||||
|
if (ret < 0) return NULL;
|
||||||
|
|
||||||
|
if(s.st_name != 0) {
|
||||||
|
ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
|
||||||
|
if (ret < 0) return NULL;
|
||||||
|
|
||||||
|
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
|
||||||
|
relocate_section(int input_fd,
|
||||||
|
struct elfloader_output *output,
|
||||||
|
unsigned int section, unsigned short size,
|
||||||
|
unsigned int sectionaddr,
|
||||||
|
char *sectionbase,
|
||||||
|
unsigned int strs,
|
||||||
|
unsigned int strtab,
|
||||||
|
unsigned int symtab, unsigned short symtabsize,
|
||||||
|
unsigned char using_relas)
|
||||||
|
{
|
||||||
|
/* sectionbase added; runtime start address of current section */
|
||||||
|
struct elf32_rela rela; /* Now used both for rel and rela data! */
|
||||||
|
int rel_size = 0;
|
||||||
|
struct elf32_sym s;
|
||||||
|
unsigned int a;
|
||||||
|
char name[30];
|
||||||
|
char *addr;
|
||||||
|
struct relevant_section *sect;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* determine correct relocation entry sizes */
|
||||||
|
if(using_relas) {
|
||||||
|
rel_size = sizeof(struct elf32_rela);
|
||||||
|
} else {
|
||||||
|
rel_size = sizeof(struct elf32_rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(a = section; a < section + size; a += rel_size) {
|
||||||
|
ret = seek_read(input_fd, a, (char *)&rela, rel_size);
|
||||||
|
if (ret < 0) return ELFLOADER_INPUT_ERROR;
|
||||||
|
ret = seek_read(input_fd,
|
||||||
|
(symtab +
|
||||||
|
sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info)),
|
||||||
|
(char *)&s, sizeof(s));
|
||||||
|
if (ret < 0) return ELFLOADER_INPUT_ERROR;
|
||||||
|
if(s.st_name != 0) {
|
||||||
|
ret = seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
|
||||||
|
if (ret < 0) return ELFLOADER_INPUT_ERROR;
|
||||||
|
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(input_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 == rodata.number) {
|
||||||
|
sect = &rodata;
|
||||||
|
} 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;
|
||||||
|
} else if(s.st_shndx == data.number) {
|
||||||
|
sect = &data;
|
||||||
|
} else if(s.st_shndx == rodata.number) {
|
||||||
|
sect = &rodata;
|
||||||
|
} else if(s.st_shndx == text.number) {
|
||||||
|
sect = &text;
|
||||||
|
} else {
|
||||||
|
return ELFLOADER_SEGMENT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = sect->address;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* We don't know how big the relocation is or even if we need to read it.
|
||||||
|
Let the architecture dependant code decide */
|
||||||
|
if (!using_relas) {
|
||||||
|
/* copy addend to rela structure */
|
||||||
|
ret = seek_read(fd, sectionaddr + rela.r_offset, &rela.r_addend, 4);
|
||||||
|
if (ret < 0) return ELFLOADER_INPUT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Copy data up to the next relocation */
|
||||||
|
unsigned int offset = elfloader_output_segment_offset(output);
|
||||||
|
if (rela.r_offset < offset) {
|
||||||
|
PRINTF("elfloader relocation out of offset order\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
if (rela.r_offset > offset) {
|
||||||
|
ret = copy_segment_data(input_fd, offset+sectionaddr, output,
|
||||||
|
rela.r_offset - offset);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = elfloader_arch_relocate(input_fd, output, sectionaddr, sectionbase,
|
||||||
|
&rela, addr);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
}
|
||||||
|
return ELFLOADER_OK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void *
|
||||||
|
find_program_processes(int input_fd,
|
||||||
|
unsigned int symtab, unsigned short size,
|
||||||
|
unsigned int strtab)
|
||||||
|
{
|
||||||
|
struct elf32_sym s;
|
||||||
|
unsigned int a;
|
||||||
|
char name[30];
|
||||||
|
|
||||||
|
for(a = symtab; a < symtab + size; a += sizeof(s)) {
|
||||||
|
seek_read(input_fd, a, (char *)&s, sizeof(s));
|
||||||
|
|
||||||
|
if(s.st_name != 0) {
|
||||||
|
seek_read(input_fd, strtab + s.st_name, name, sizeof(name));
|
||||||
|
if(strcmp(name, "autostart_processes") == 0) {
|
||||||
|
return &data.address[s.st_value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 */
|
||||||
|
|
||||||
|
static int
|
||||||
|
copy_segment(int input_fd,
|
||||||
|
struct elfloader_output *output,
|
||||||
|
unsigned int section, unsigned short size,
|
||||||
|
unsigned int sectionaddr,
|
||||||
|
char *sectionbase,
|
||||||
|
unsigned int strs,
|
||||||
|
unsigned int strtab,
|
||||||
|
unsigned int symtab, unsigned short symtabsize,
|
||||||
|
unsigned char using_relas,
|
||||||
|
unsigned int seg_size, unsigned int seg_type)
|
||||||
|
{
|
||||||
|
unsigned int offset;
|
||||||
|
int ret;
|
||||||
|
ret = elfloader_output_start_segment(output, seg_type,sectionbase, seg_size);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
ret = relocate_section(input_fd, output,
|
||||||
|
section, size,
|
||||||
|
sectionaddr,
|
||||||
|
sectionbase,
|
||||||
|
strs,
|
||||||
|
strtab,
|
||||||
|
symtab, symtabsize, using_relas);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
offset = elfloader_output_segment_offset(output);
|
||||||
|
ret = copy_segment_data(input_fd, offset+sectionaddr, output,seg_size - offset);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
return elfloader_output_end_segment(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
elfloader_load(int input_fd, struct elfloader_output *output)
|
||||||
|
{
|
||||||
|
struct elf32_ehdr ehdr;
|
||||||
|
struct elf32_shdr shdr;
|
||||||
|
struct elf32_shdr strtable;
|
||||||
|
unsigned int strs;
|
||||||
|
unsigned int shdrptr;
|
||||||
|
unsigned int nameptr;
|
||||||
|
char name[12];
|
||||||
|
|
||||||
|
int i;
|
||||||
|
unsigned short shdrnum, shdrsize;
|
||||||
|
|
||||||
|
unsigned char using_relas = -1;
|
||||||
|
unsigned short textoff = 0, textsize, textrelaoff = 0, textrelasize;
|
||||||
|
unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
|
||||||
|
unsigned short rodataoff = 0, rodatasize, rodatarelaoff = 0, rodatarelasize;
|
||||||
|
unsigned short symtaboff = 0, symtabsize;
|
||||||
|
unsigned short strtaboff = 0, strtabsize;
|
||||||
|
unsigned short bsssize = 0;
|
||||||
|
|
||||||
|
struct process **process;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
elfloader_unknown[0] = 0;
|
||||||
|
|
||||||
|
/* The ELF header is located at the start of the buffer. */
|
||||||
|
ret = seek_read(input_fd, 0, (char *)&ehdr, sizeof(ehdr));
|
||||||
|
if (ret != sizeof(ehdr)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
|
||||||
|
PRINTF("ELF header problems\n");
|
||||||
|
return ELFLOADER_BAD_ELF_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab the section header. */
|
||||||
|
shdrptr = ehdr.e_shoff;
|
||||||
|
ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
|
||||||
|
if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
|
||||||
|
/* Get the size and number of entries of the section header. */
|
||||||
|
shdrsize = ehdr.e_shentsize;
|
||||||
|
shdrnum = ehdr.e_shnum;
|
||||||
|
|
||||||
|
/* The string table section: holds the names of the sections. */
|
||||||
|
ret = seek_read(input_fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
|
||||||
|
(char *)&strtable, sizeof(strtable));
|
||||||
|
if (ret != sizeof(strtable)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
file (these are in the sybtam section). */
|
||||||
|
strs = strtable.sh_offset;
|
||||||
|
|
||||||
|
/* Go through all sections and pick out the relevant ones. The
|
||||||
|
".text" segment holds the actual code from the ELF file, the
|
||||||
|
".data" segment contains initialized data, the ".rodata" segment
|
||||||
|
contains read-only data, the ".bss" segment holds the size of the
|
||||||
|
unitialized data segment. The ".rel[a].text" and ".rel[a].data"
|
||||||
|
segments contains relocation information for the contents of the
|
||||||
|
".text" and ".data" segments, respectively. The ".symtab" segment
|
||||||
|
contains the symbol table for this file. The ".strtab" segment
|
||||||
|
points to the actual string names used by the symbol table.
|
||||||
|
|
||||||
|
In addition to grabbing pointers to the relevant sections, we
|
||||||
|
also save the section number for resolving addresses in the
|
||||||
|
relocator code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize the segment sizes to zero so that we can check if
|
||||||
|
their sections was found in the file or not. */
|
||||||
|
textsize = textrelasize = datasize = datarelasize =
|
||||||
|
rodatasize = rodatarelasize = symtabsize = strtabsize = 0;
|
||||||
|
|
||||||
|
bss.number = data.number = rodata.number = text.number = -1;
|
||||||
|
|
||||||
|
shdrptr = ehdr.e_shoff;
|
||||||
|
for(i = 0; i < shdrnum; ++i) {
|
||||||
|
|
||||||
|
ret = seek_read(input_fd, shdrptr, (char *)&shdr, sizeof(shdr));
|
||||||
|
if (ret != sizeof(shdr)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
|
||||||
|
/* The name of the section is contained in the strings table. */
|
||||||
|
nameptr = strs + shdr.sh_name;
|
||||||
|
ret = seek_read(input_fd, nameptr, name, sizeof(name));
|
||||||
|
if (ret != sizeof(name)) return ELFLOADER_INPUT_ERROR;
|
||||||
|
|
||||||
|
/* Match the name of the section with a predefined set of names
|
||||||
|
(.text, .data, .bss, .rela.text, .rela.data, .symtab, and
|
||||||
|
.strtab). */
|
||||||
|
/* added support for .rodata, .rel.text and .rel.data). */
|
||||||
|
|
||||||
|
if(strncmp(name, ".text", 5) == 0) {
|
||||||
|
textoff = shdr.sh_offset;
|
||||||
|
textsize = shdr.sh_size;
|
||||||
|
text.number = i;
|
||||||
|
text.offset = textoff;
|
||||||
|
} else if(strncmp(name, ".rel.text", 9) == 0) {
|
||||||
|
using_relas = 0;
|
||||||
|
textrelaoff = shdr.sh_offset;
|
||||||
|
textrelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".rela.text", 10) == 0) {
|
||||||
|
using_relas = 1;
|
||||||
|
textrelaoff = shdr.sh_offset;
|
||||||
|
textrelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".data", 5) == 0) {
|
||||||
|
dataoff = shdr.sh_offset;
|
||||||
|
datasize = shdr.sh_size;
|
||||||
|
data.number = i;
|
||||||
|
data.offset = dataoff;
|
||||||
|
} else if(strncmp(name, ".rodata", 7) == 0) {
|
||||||
|
/* read-only data handled the same way as regular text section */
|
||||||
|
rodataoff = shdr.sh_offset;
|
||||||
|
rodatasize = shdr.sh_size;
|
||||||
|
rodata.number = i;
|
||||||
|
rodata.offset = rodataoff;
|
||||||
|
} else if(strncmp(name, ".rel.rodata", 11) == 0) {
|
||||||
|
/* using elf32_rel instead of rela */
|
||||||
|
using_relas = 0;
|
||||||
|
rodatarelaoff = shdr.sh_offset;
|
||||||
|
rodatarelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".rela.rodata", 12) == 0) {
|
||||||
|
using_relas = 1;
|
||||||
|
rodatarelaoff = shdr.sh_offset;
|
||||||
|
rodatarelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".rel.data", 9) == 0) {
|
||||||
|
/* using elf32_rel instead of rela */
|
||||||
|
using_relas = 0;
|
||||||
|
datarelaoff = shdr.sh_offset;
|
||||||
|
datarelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".rela.data", 10) == 0) {
|
||||||
|
using_relas = 1;
|
||||||
|
datarelaoff = shdr.sh_offset;
|
||||||
|
datarelasize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".symtab", 7) == 0) {
|
||||||
|
symtaboff = shdr.sh_offset;
|
||||||
|
symtabsize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".strtab", 7) == 0) {
|
||||||
|
strtaboff = shdr.sh_offset;
|
||||||
|
strtabsize = shdr.sh_size;
|
||||||
|
} else if(strncmp(name, ".bss", 4) == 0) {
|
||||||
|
bsssize = shdr.sh_size;
|
||||||
|
bss.number = i;
|
||||||
|
bss.offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move on to the next section header. */
|
||||||
|
shdrptr += shdrsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(symtabsize == 0) {
|
||||||
|
return ELFLOADER_NO_SYMTAB;
|
||||||
|
}
|
||||||
|
if(strtabsize == 0) {
|
||||||
|
return ELFLOADER_NO_STRTAB;
|
||||||
|
}
|
||||||
|
if(textsize == 0) {
|
||||||
|
return ELFLOADER_NO_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bsssize) {
|
||||||
|
bss.address = (char *)
|
||||||
|
elfloader_output_alloc_segment(output, ELFLOADER_SEG_BSS, bsssize);
|
||||||
|
if (!bss.address) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
}
|
||||||
|
if (datasize) {
|
||||||
|
data.address = (char *)
|
||||||
|
elfloader_output_alloc_segment(output,ELFLOADER_SEG_DATA,datasize);
|
||||||
|
if (!data.address) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
}
|
||||||
|
if (textsize) {
|
||||||
|
text.address = (char *)
|
||||||
|
elfloader_output_alloc_segment(output,ELFLOADER_SEG_TEXT,textsize);
|
||||||
|
if (!text.address) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
}
|
||||||
|
if (rodatasize) {
|
||||||
|
rodata.address = (char *)
|
||||||
|
elfloader_output_alloc_segment(output,ELFLOADER_SEG_RODATA,rodatasize);
|
||||||
|
if (!rodata.address) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* printf("bss base address: bss.address = 0x%08x\n", bss.address);
|
||||||
|
printf("data base address: data.address = 0x%08x\n", data.address);
|
||||||
|
printf("text base address: text.address = 0x%08x\n", text.address);
|
||||||
|
printf("rodata base address: rodata.address = 0x%08x\n", rodata.address); */
|
||||||
|
|
||||||
|
|
||||||
|
/* If we have text segment relocations, we process them. */
|
||||||
|
PRINTF("elfloader: relocate text\n");
|
||||||
|
if(textrelasize > 0) {
|
||||||
|
ret = copy_segment(input_fd, output,
|
||||||
|
textrelaoff, textrelasize,
|
||||||
|
textoff,
|
||||||
|
text.address,
|
||||||
|
strs,
|
||||||
|
strtaboff,
|
||||||
|
symtaboff, symtabsize, using_relas,
|
||||||
|
textsize, ELFLOADER_SEG_TEXT);
|
||||||
|
if(ret != ELFLOADER_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have any rodata segment relocations, we process them too. */
|
||||||
|
PRINTF("elfloader: relocate rodata\n");
|
||||||
|
if(rodatarelasize > 0) {
|
||||||
|
ret = copy_segment(input_fd, output,
|
||||||
|
rodatarelaoff, rodatarelasize,
|
||||||
|
rodataoff,
|
||||||
|
rodata.address,
|
||||||
|
strs,
|
||||||
|
strtaboff,
|
||||||
|
symtaboff, symtabsize, using_relas,
|
||||||
|
rodatasize, ELFLOADER_SEG_RODATA);
|
||||||
|
if(ret != ELFLOADER_OK) {
|
||||||
|
PRINTF("elfloader: data failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have any data segment relocations, we process them too. */
|
||||||
|
PRINTF("elfloader: relocate data\n");
|
||||||
|
if(datarelasize > 0) {
|
||||||
|
ret = copy_segment(input_fd, output,
|
||||||
|
datarelaoff, datarelasize,
|
||||||
|
dataoff,
|
||||||
|
data.address,
|
||||||
|
strs,
|
||||||
|
strtaboff,
|
||||||
|
symtaboff, symtabsize, using_relas,
|
||||||
|
datasize, ELFLOADER_SEG_DATA);
|
||||||
|
if(ret != ELFLOADER_OK) {
|
||||||
|
PRINTF("elfloader: data failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = elfloader_output_end_segment(output);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write text and rodata segment into flash and data segment into RAM. */
|
||||||
|
/* elfloader_arch_write_rom(fd, textoff, textsize, text.address); */
|
||||||
|
/* elfloader_arch_write_rom(fd, rodataoff, rodatasize, rodata.address); */
|
||||||
|
|
||||||
|
/* memset(bss.address, 0, bsssize); */
|
||||||
|
/* seek_read(fd, dataoff, data.address, datasize); */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Write zeros to bss segment */
|
||||||
|
unsigned int len = bsssize;
|
||||||
|
static const char zeros[16] = {0};
|
||||||
|
ret = elfloader_output_start_segment(output, ELFLOADER_SEG_BSS,
|
||||||
|
bss.address,bsssize);
|
||||||
|
if (ret != ELFLOADER_OK) return ret;
|
||||||
|
while(len > sizeof(zeros)) {
|
||||||
|
ret = elfloader_output_write_segment(output, zeros, sizeof(zeros));
|
||||||
|
if (ret != sizeof(zeros)) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
len -= sizeof(zeros);
|
||||||
|
}
|
||||||
|
ret = elfloader_output_write_segment(output, zeros, len);
|
||||||
|
if (ret != len) return ELFLOADER_OUTPUT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTF("elfloader: autostart search\n");
|
||||||
|
process = find_local_symbol(input_fd, "autostart_processes", symtaboff, symtabsize, strtaboff);
|
||||||
|
if(process != NULL) {
|
||||||
|
PRINTF("elfloader: autostart found\n");
|
||||||
|
elfloader_autostart_processes = process;
|
||||||
|
return ELFLOADER_OK;
|
||||||
|
} else {
|
||||||
|
PRINTF("elfloader: no autostart\n");
|
||||||
|
process = find_program_processes(input_fd, symtaboff, symtabsize, strtaboff);
|
||||||
|
if(process != NULL) {
|
||||||
|
PRINTF("elfloader: FOUND PRG\n");
|
||||||
|
}
|
||||||
|
return ELFLOADER_NO_STARTPOINT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
314
cpu/arm/at91sam7s/loader/elfloader-otf.h
Normal file
314
cpu/arm/at91sam7s/loader/elfloader-otf.h
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
/**
|
||||||
|
* \addtogroup loader
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \defgroup elfloader The Contiki ELF loader
|
||||||
|
*
|
||||||
|
* The Contiki ELF loader links, relocates, and loads ELF
|
||||||
|
* (Executable Linkable Format) object files into a running Contiki
|
||||||
|
* system.
|
||||||
|
*
|
||||||
|
* ELF is a standard format for relocatable object code and executable
|
||||||
|
* files. ELF is the standard program format for Linux, Solaris, and
|
||||||
|
* other operating systems.
|
||||||
|
*
|
||||||
|
* An ELF file contains either a standalone executable program or a
|
||||||
|
* program module. The file contains both the program code, the
|
||||||
|
* program data, as well as information about how to link, relocate,
|
||||||
|
* and load the program into a running system.
|
||||||
|
*
|
||||||
|
* The ELF file is composed of a set of sections. The sections contain
|
||||||
|
* program code, data, or relocation information, but can also contain
|
||||||
|
* debugging information.
|
||||||
|
*
|
||||||
|
* To link and relocate an ELF file, the Contiki ELF loader first
|
||||||
|
* parses the ELF file structure to find the appropriate ELF
|
||||||
|
* sections. It then allocates memory for the program code and data in
|
||||||
|
* ROM and RAM, respectively. After allocating memory, the Contiki ELF
|
||||||
|
* loader starts relocating the code found in the ELF file.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Header file for the Contiki ELF loader.
|
||||||
|
* \author
|
||||||
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
* Simon Berg <ksb@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||||
|
* Copyright (c) 2007, Simon Berg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 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
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* 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
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ELFLOADER_H__
|
||||||
|
#define __ELFLOADER_H__
|
||||||
|
|
||||||
|
#include "cfs/cfs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that loading worked.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_OK 0
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that the ELF file had
|
||||||
|
* a bad header.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_BAD_ELF_HEADER 1
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that no symbol table
|
||||||
|
* could be find in the ELF file.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_NO_SYMTAB 2
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that no string table
|
||||||
|
* could be find in the ELF file.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_NO_STRTAB 3
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that the size of the
|
||||||
|
* .text segment was zero.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_NO_TEXT 4
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that a symbol
|
||||||
|
* specific symbol could not be found.
|
||||||
|
*
|
||||||
|
* If this value is returned from elfloader_load(), the symbol has
|
||||||
|
* been copied into the elfloader_unknown[] array.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_SYMBOL_NOT_FOUND 5
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that one of the
|
||||||
|
* required segments (.data, .bss, or .text) could not be found.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_SEGMENT_NOT_FOUND 6
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that no starting
|
||||||
|
* point could be found in the loaded module.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_NO_STARTPOINT 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that the ELF file contained
|
||||||
|
* a relocation type that the implementation can't handle.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_UNHANDLED_RELOC 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that the offset for
|
||||||
|
* a relative addressing mode was too big.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_OUTOF_RANGE 9
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that the relocations
|
||||||
|
* where not sorted by offset
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_RELOC_NOT_SORTED 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that reading from the
|
||||||
|
* ELF file failed in some way.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_INPUT_ERROR 11
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value from elfloader_load() indicating that writing to a segment
|
||||||
|
* failed.
|
||||||
|
*/
|
||||||
|
#define ELFLOADER_OUTPUT_ERROR 12
|
||||||
|
|
||||||
|
|
||||||
|
#define ELFLOADER_SEG_TEXT 1
|
||||||
|
#define ELFLOADER_SEG_RODATA 2
|
||||||
|
#define ELFLOADER_SEG_DATA 3
|
||||||
|
#define ELFLOADER_SEG_BSS 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* elfloader output object
|
||||||
|
*
|
||||||
|
* This object defines methods (callbacks) for writing the segments to memory.
|
||||||
|
* It can be extended by the user to include any necessary state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct elfloader_output {
|
||||||
|
const struct elfloader_output_ops *ops;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* \brief Allocate a new segment
|
||||||
|
* \param input The output object
|
||||||
|
* \param type Type of segment
|
||||||
|
* \param size Size of segment in bytes
|
||||||
|
* \return A pointer to the start of the segment.
|
||||||
|
*
|
||||||
|
* The returned address doesn't need to correspond to any real memory,
|
||||||
|
* since it's only used for calculating the relocations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void *elfloader_allocate_segment(struct elfloader_output *output,
|
||||||
|
unsigned int type, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Start writing to a new segment
|
||||||
|
* \param input The output object
|
||||||
|
* \param type Type of segment
|
||||||
|
* \param addr Address of segment from elfloader_allocate_segment
|
||||||
|
* \param size Size of segment in bytes
|
||||||
|
* \return Returns ELFLOADER_OK if successful, otherwise an error code
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int elfloader_start_segment(struct elfloader_output *output,
|
||||||
|
unsigned int type, void *addr, int size);
|
||||||
|
/**
|
||||||
|
* \brief Mark end of segment
|
||||||
|
* \param input The output object
|
||||||
|
* \return Zero if successful
|
||||||
|
*/
|
||||||
|
|
||||||
|
int elfloader_end_segment(struct elfloader_output *output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Write data to a segment
|
||||||
|
* \param input The output object
|
||||||
|
* \param buf Data to be written
|
||||||
|
* \param len Length of data
|
||||||
|
* \return The number of bytes actually written, or negative if failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int elfloader_write_segment(struct elfloader_output *output, const char *buf,
|
||||||
|
unsigned int len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the current offset in the file where the next data will
|
||||||
|
* be written.
|
||||||
|
* \param input The output object
|
||||||
|
* \return The current offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned int elfloader_segment_offset(struct elfloader_output *output);
|
||||||
|
|
||||||
|
#define elfloader_output_alloc_segment(output, type, size) \
|
||||||
|
((output)->ops->allocate_segment(output, type, size))
|
||||||
|
|
||||||
|
#define elfloader_output_start_segment(output, type, addr, size) \
|
||||||
|
((output)->ops->start_segment(output, type, addr, size))
|
||||||
|
|
||||||
|
#define elfloader_output_end_segment(output) \
|
||||||
|
((output)->ops->end_segment(output))
|
||||||
|
|
||||||
|
#define elfloader_output_write_segment(output, buf, len) \
|
||||||
|
((output)->ops->write_segment(output, buf, len))
|
||||||
|
|
||||||
|
#define elfloader_output_segment_offset(output) \
|
||||||
|
((output)->ops->segment_offset(output))
|
||||||
|
|
||||||
|
|
||||||
|
struct elfloader_output_ops {
|
||||||
|
void * (*allocate_segment)(struct elfloader_output *output,
|
||||||
|
unsigned int type, int size);
|
||||||
|
int (*start_segment)(struct elfloader_output *output,
|
||||||
|
unsigned int type, void *addr, int size);
|
||||||
|
int (*end_segment)(struct elfloader_output *output);
|
||||||
|
int (*write_segment)(struct elfloader_output *output, const char *buf,
|
||||||
|
unsigned int len);
|
||||||
|
unsigned int (*segment_offset)(struct elfloader_output *output);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* elfloader initialization function.
|
||||||
|
*
|
||||||
|
* This function should be called at boot up to initilize the elfloader.
|
||||||
|
*/
|
||||||
|
void elfloader_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Load and relocate an ELF file.
|
||||||
|
* \param input Input object defining how to read from the ELF file
|
||||||
|
* \param output Output object defining how to create and write to seegments.
|
||||||
|
* \return ELFLOADER_OK if loading and relocation worked.
|
||||||
|
* Otherwise an error value.
|
||||||
|
*
|
||||||
|
* If the function is able to load the ELF file, a pointer
|
||||||
|
* to the process structure in the model is stored in the
|
||||||
|
* elfloader_loaded_process variable.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int elfloader_load(int input_fd,
|
||||||
|
struct elfloader_output *output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to the processes loaded with elfloader_load().
|
||||||
|
*/
|
||||||
|
extern struct process **elfloader_autostart_processes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If elfloader_load() could not find a specific symbol, it is copied
|
||||||
|
* into this array.
|
||||||
|
*/
|
||||||
|
extern char elfloader_unknown[30];
|
||||||
|
|
||||||
|
#ifdef ELFLOADER_CONF_DATAMEMORY_SIZE
|
||||||
|
#define ELFLOADER_DATAMEMORY_SIZE ELFLOADER_CONF_DATAMEMORY_SIZE
|
||||||
|
#else
|
||||||
|
#define ELFLOADER_DATAMEMORY_SIZE 0x100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ELFLOADER_CONF_TEXTMEMORY_SIZE
|
||||||
|
#define ELFLOADER_TEXTMEMORY_SIZE ELFLOADER_CONF_TEXTMEMORY_SIZE
|
||||||
|
#else
|
||||||
|
#define ELFLOADER_TEXTMEMORY_SIZE 0x100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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_rela {
|
||||||
|
elf32_addr r_offset; /* Location to be relocated. */
|
||||||
|
elf32_word r_info; /* Relocation type and symbol index. */
|
||||||
|
elf32_sword r_addend; /* Addend. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __ELFLOADER_H__ */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
/** @} */
|
3
cpu/arm/at91sam7s/loader/empty-symbols.c
Normal file
3
cpu/arm/at91sam7s/loader/empty-symbols.c
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include "symbols.h"
|
||||||
|
const int symbols_nelts = 0;
|
||||||
|
const struct symbols symbols[] = {{0,0}};
|
139
cpu/arm/at91sam7s/loader/ram-segments.c
Normal file
139
cpu/arm/at91sam7s/loader/ram-segments.c
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#ifndef __RAM_SEGMENTS_C__1POIF5E8U4__
|
||||||
|
#define __RAM_SEGMENTS_C__1POIF5E8U4__
|
||||||
|
|
||||||
|
#include <loader/elfloader-otf.h>
|
||||||
|
#include <loader/codeprop-otf.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct ram_output
|
||||||
|
{
|
||||||
|
struct elfloader_output output;
|
||||||
|
char *base;
|
||||||
|
unsigned int offset;
|
||||||
|
void *text;
|
||||||
|
void *rodata;
|
||||||
|
void *data;
|
||||||
|
void *bss;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
allocate_segment(struct elfloader_output * const output,
|
||||||
|
unsigned int type, int size)
|
||||||
|
{
|
||||||
|
struct ram_output * const ram = (struct ram_output *)output;
|
||||||
|
void *block = malloc(size);
|
||||||
|
if (!block) return NULL;
|
||||||
|
switch(type) {
|
||||||
|
case ELFLOADER_SEG_TEXT:
|
||||||
|
if (ram->text) free(ram->text);
|
||||||
|
ram->text = block;
|
||||||
|
break;
|
||||||
|
case ELFLOADER_SEG_RODATA:
|
||||||
|
if (ram->rodata) free(ram->rodata);
|
||||||
|
ram->rodata = block;
|
||||||
|
break;
|
||||||
|
case ELFLOADER_SEG_DATA:
|
||||||
|
if (ram->data) free(ram->data);
|
||||||
|
ram->data = block;
|
||||||
|
break;
|
||||||
|
case ELFLOADER_SEG_BSS:
|
||||||
|
if (ram->bss) free(ram->bss);
|
||||||
|
ram->bss = block;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
free(block);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
start_segment(struct elfloader_output *output,
|
||||||
|
unsigned int type, void *addr, int size)
|
||||||
|
{
|
||||||
|
((struct ram_output*)output)->base = addr;
|
||||||
|
((struct ram_output*)output)->offset = 0;
|
||||||
|
return ELFLOADER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
end_segment(struct elfloader_output *output)
|
||||||
|
{
|
||||||
|
return ELFLOADER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_segment(struct elfloader_output *output, const char *buf,
|
||||||
|
unsigned int len)
|
||||||
|
{
|
||||||
|
struct ram_output * const ram = (struct ram_output *)output;
|
||||||
|
memcpy(ram->base + ram->offset, buf, len);
|
||||||
|
ram->offset += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
segment_offset(struct elfloader_output *output)
|
||||||
|
{
|
||||||
|
return ((struct ram_output*)output)->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct elfloader_output_ops elf_output_ops =
|
||||||
|
{
|
||||||
|
allocate_segment,
|
||||||
|
start_segment,
|
||||||
|
end_segment,
|
||||||
|
write_segment,
|
||||||
|
segment_offset
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct ram_output seg_output = {
|
||||||
|
{&elf_output_ops},
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
PROCESS(ram_segments_cleanup_process, "RAM segments cleanup process");
|
||||||
|
|
||||||
|
PROCESS_THREAD(ram_segments_cleanup_process, ev, data)
|
||||||
|
{
|
||||||
|
PROCESS_BEGIN();
|
||||||
|
while(1) {
|
||||||
|
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_EXITED
|
||||||
|
|| ev == PROCESS_EVENT_EXIT);
|
||||||
|
if (ev == PROCESS_EVENT_EXIT) break;
|
||||||
|
if (elfloader_autostart_processes ||
|
||||||
|
elfloader_autostart_processes[0] == data) {
|
||||||
|
PROCESS_PAUSE(); /* Let the process exit */
|
||||||
|
if (seg_output.text) {
|
||||||
|
free(seg_output.text);
|
||||||
|
seg_output.text = NULL;
|
||||||
|
}
|
||||||
|
if (seg_output.rodata) {
|
||||||
|
free(seg_output.rodata);
|
||||||
|
seg_output.rodata = NULL;
|
||||||
|
}
|
||||||
|
if (seg_output.data) {
|
||||||
|
free(seg_output.data);
|
||||||
|
seg_output.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seg_output.bss) {
|
||||||
|
free(seg_output.bss);
|
||||||
|
seg_output.bss = NULL;
|
||||||
|
}
|
||||||
|
elfloader_autostart_processes = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PROCESS_END();
|
||||||
|
}
|
||||||
|
struct elfloader_output *codeprop_output = &seg_output.output;
|
||||||
|
|
||||||
|
#endif /* __RAM_SEGMENTS_C__1POIF5E8U4__ */
|
6
cpu/arm/at91sam7s/loader/ram-segments.h
Normal file
6
cpu/arm/at91sam7s/loader/ram-segments.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __RAM_SEGMENTS_H__8EDB9N09UD__
|
||||||
|
#define __RAM_SEGMENTS_H__8EDB9N09UD__
|
||||||
|
|
||||||
|
PROCESS_NAME(ram_segments_cleanup_process);
|
||||||
|
|
||||||
|
#endif /* __RAM_SEGMENTS_H__8EDB9N09UD__ */
|
Loading…
Reference in a new issue