From 4e62a35e8393a6b0796238129a0e79eb24addf43 Mon Sep 17 00:00:00 2001 From: bg- Date: Fri, 1 Dec 2006 15:15:08 +0000 Subject: [PATCH] * Backwards compatible with elfloader.c but uses the new Contiki link-editor. Taken together cle and elfloader_compat requires less ROM and RAM than the old version. --- core/loader/elfloader_compat.c | 196 +++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 core/loader/elfloader_compat.c diff --git a/core/loader/elfloader_compat.c b/core/loader/elfloader_compat.c new file mode 100644 index 000000000..ff80c9653 --- /dev/null +++ b/core/loader/elfloader_compat.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2006, 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: elfloader_compat.c,v 1.1 2006/12/01 15:15:08 bg- Exp $ + */ + +/* + * This code is plug-in compatible with elfloader.c and is an example + * of how the Contiki dynamic Link Editor (CLE) can be used. + */ + +#include +#include +#include + +#include + +#include "contiki.h" + +#include "loader/elfloader.h" +#include "loader/cle.h" + +#include "lib/malloc.h" +#include "dev/rom.h" +#include "dev/xmem.h" + +#define NDEBUG +#include "lib/assert.h" + +#ifdef NDEBUG +#define PRINTF(...) do {} while (0) +#else +#define PRINTF(...) printf(__VA_ARGS__) +#endif + +struct process *elfloader_loaded_process; +void (*elfloader_fini)(void); + +#define IMAX(a, b) (((a) > (b)) ? (a) : (b)) + +static cle_addr datamemory; + +#define TEXTMEMORY \ + (cle_addr)(((uintptr_t)(&_etext + 1) \ + + (uintptr_t)&_edata - (uintptr_t)&__data_start \ + + ROM_ERASE_UNIT_SIZE) \ + & ~(ROM_ERASE_UNIT_SIZE - 1)) + +char elfloader_unknown[30]; /* Name that caused link error. */ + +/*---------------------------------------------------------------------------*/ +int +elfloader_load(off_t eepromaddr) +{ + struct cle_info h; + int ret; + + void (*elfloader_init)(void); + + elfloader_unknown[0] = 0; + + /* The ELF header is located at the start of the buffer. */ + ret = cle_read_info(&h, xmem_pread, eepromaddr); + + if(ret != ELFLOADER_OK) { + memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); + elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; + return ret; + } + + if(datamemory != NULL) { + free(datamemory); + } + + /* We are making semi-permanent allocations, first compact heap! */ + malloc_compact(); + datamemory = malloc(IMAX(h.textsize, h.datasize + h.bsssize)); + if(datamemory == NULL) { + return ELFLOADER_DATA_TO_LARGE; /* XXX or text to large */ + } + + h.data = datamemory; + h.bss = h.data + h.datasize; + h.text = TEXTMEMORY; + + PRINTF("elfloader: copy text segment to RAM %p %p\n", + h.data, h.data + h.textsize); + ret = xmem_pread(datamemory, h.textsize, eepromaddr + h.textoff); + assert(ret > 0); + if(h.textrelasize > 0) { + PRINTF("elfloader: relocate text in RAM\n"); + ret = cle_relocate(&h, + xmem_pread, + eepromaddr, + datamemory, + h.textrelaoff, h.textrelasize); + if(ret != ELFLOADER_OK) { + memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); + elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; + return ret; + } + } + PRINTF("elfloader: copy text segment to ROM %p %p\n", + h.text, h.text + h.textsize); + ret = rom_erase((h.textsize+ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE-1), + (uintptr_t)h.text); + assert(ret > 0); + ret = rom_pwrite(datamemory, h.textsize, (uintptr_t)h.text); + assert(ret > 0); + + PRINTF("elfloader: copy data segment to RAM %p %p\n", + h.data, h.data + h.datasize); + ret = xmem_pread(datamemory, h.datasize, eepromaddr + h.dataoff); + assert(ret > 0); + if(h.datarelasize > 0) { + PRINTF("elfloader: relocate data segment\n"); + ret = cle_relocate(&h, + xmem_pread, + eepromaddr, + datamemory, + h.datarelaoff, h.datarelasize); + if(ret != ELFLOADER_OK) { + memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); + elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; + return ret; + } + } + + PRINTF("elfloader: zero bss %p %p\n", h.bss, h.bss + h.bsssize); + memset(h.bss, 0, h.bsssize); + + /* Find _init, _fini, and loaded_process. */ + elfloader_loaded_process = cle_lookup(&h, xmem_pread, eepromaddr, + "process_load"); + elfloader_fini = cle_lookup(&h, xmem_pread, eepromaddr, "_fini"); + elfloader_init = cle_lookup(&h, xmem_pread, eepromaddr, "_init"); + + 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; + } else { + 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; + } +}