Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2006, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$Id: elfloader_compat.c,v 1.7 2008/02/07 15:53:43 oliverschmidt Exp $ 00032 */ 00033 00034 /* 00035 * This code is plug-in compatible with elfloader.c and is an example 00036 * of how the Contiki dynamic Link Editor (CLE) can be used. 00037 */ 00038 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 00043 #include "contiki.h" 00044 00045 #include "loader/elfloader_compat.h" 00046 #include "loader/cle.h" 00047 00048 #include "lib/malloc.h" 00049 #include "dev/rom.h" 00050 #include "dev/xmem.h" 00051 00052 #define NDEBUG 00053 #include "lib/assert.h" 00054 00055 #ifdef NDEBUG 00056 #define PRINTF(...) do {} while (0) 00057 #else 00058 #define PRINTF(...) printf(__VA_ARGS__) 00059 #endif 00060 00061 struct process *elfloader_loaded_process; 00062 void (*elfloader_fini)(void); 00063 00064 #define IMAX(a, b) (((a) > (b)) ? (a) : (b)) 00065 00066 unsigned char *datamemory; 00067 00068 #ifdef __AVR__ 00069 extern int __data_load_end; 00070 #define TEXTMEMORY (((cle_addr)(&__data_load_end) + ROM_ERASE_UNIT_SIZE) \ 00071 & ~(ROM_ERASE_UNIT_SIZE - 1)) 00072 #else 00073 #include <sys/unistd.h> 00074 #define TEXTMEMORY \ 00075 (cle_addr)(((uintptr_t)(&_etext + 1) \ 00076 + (uintptr_t)&_edata - (uintptr_t)&__data_start \ 00077 + ROM_ERASE_UNIT_SIZE) \ 00078 & ~(ROM_ERASE_UNIT_SIZE - 1)) 00079 #endif 00080 00081 char elfloader_unknown[30]; /* Name that caused link error. */ 00082 00083 /*---------------------------------------------------------------------------*/ 00084 int 00085 elfloader_load(off_t eepromaddr) 00086 { 00087 struct cle_info h; 00088 int ret; 00089 00090 void (*elfloader_init)(void); 00091 00092 elfloader_unknown[0] = 0; 00093 00094 /* The ELF header is located at the start of the buffer. */ 00095 ret = cle_read_info(&h, xmem_pread, eepromaddr); 00096 00097 if(ret != ELFLOADER_OK) { 00098 memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); 00099 elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; 00100 return ret; 00101 } 00102 00103 if(datamemory != NULL) { 00104 free(datamemory); 00105 } 00106 00107 /* We are making semi-permanent allocations, first compact heap! */ 00108 /* malloc_compact(); */ 00109 datamemory = malloc(IMAX(h.textsize, h.datasize + h.bsssize)); 00110 if(datamemory == NULL) { 00111 return ELFLOADER_DATA_TO_LARGE; /* XXX or text to large */ 00112 } 00113 00114 h.data = datamemory; 00115 h.bss = datamemory + h.datasize; 00116 h.text = TEXTMEMORY; 00117 00118 PRINTF("elfloader: copy text segment to RAM %p %p\n", 00119 h.data, h.data + h.textsize); 00120 ret = xmem_pread(datamemory, h.textsize, eepromaddr + h.textoff); 00121 assert(ret > 0); 00122 if(h.textrelasize > 0) { 00123 PRINTF("elfloader: relocate text in RAM\n"); 00124 ret = cle_relocate(&h, 00125 xmem_pread, 00126 eepromaddr, 00127 datamemory, 00128 h.textrelaoff, h.textrelasize); 00129 if(ret != ELFLOADER_OK) { 00130 memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); 00131 elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; 00132 return ret; 00133 } 00134 } 00135 PRINTF("elfloader: copy text segment to ROM 0x%lx 0x%lx\n", 00136 (unsigned long)h.text, 00137 (unsigned long)h.text + h.textsize); 00138 00139 ret = rom_erase((h.textsize+ROM_ERASE_UNIT_SIZE) & ~(ROM_ERASE_UNIT_SIZE-1), 00140 h.text); 00141 assert(ret > 0); 00142 ret = rom_pwrite(datamemory, h.textsize, h.text); 00143 assert(ret > 0); 00144 00145 PRINTF("elfloader: copy data segment to RAM %p %p\n", 00146 h.data, h.data + h.datasize); 00147 ret = xmem_pread(datamemory, h.datasize, eepromaddr + h.dataoff); 00148 assert(ret >= h.datasize); 00149 if(h.datarelasize > 0) { 00150 PRINTF("elfloader: relocate data segment\n"); 00151 ret = cle_relocate(&h, 00152 xmem_pread, 00153 eepromaddr, 00154 datamemory, 00155 h.datarelaoff, h.datarelasize); 00156 if(ret != ELFLOADER_OK) { 00157 memcpy(elfloader_unknown, h.name, sizeof(elfloader_unknown)); 00158 elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0; 00159 return ret; 00160 } 00161 } 00162 00163 PRINTF("elfloader: zero bss %p %p\n", h.bss, h.bss + h.bsssize); 00164 memset(h.bss, 0, h.bsssize); 00165 00166 /* Find _init, _fini, and loaded_process. */ 00167 elfloader_loaded_process = cle_lookup(&h, xmem_pread, eepromaddr, 00168 "autostart_processes"); 00169 elfloader_fini = cle_lookup(&h, xmem_pread, eepromaddr, "_fini"); 00170 elfloader_init = cle_lookup(&h, xmem_pread, eepromaddr, "_init"); 00171 00172 if(elfloader_init != NULL) { 00173 PRINTF("init=%p fini=%p\n", elfloader_init, elfloader_fini); 00174 (*elfloader_init)(); 00175 elfloader_loaded_process = NULL; 00176 return ELFLOADER_OK; 00177 } 00178 00179 if(elfloader_loaded_process != NULL) { 00180 PRINTF("elfloader: launch program\n"); 00181 process_start(elfloader_loaded_process, NULL); 00182 elfloader_fini = NULL; 00183 return ELFLOADER_OK; 00184 } else { 00185 return ELFLOADER_NO_STARTPOINT; 00186 } 00187 } 00188 /*---------------------------------------------------------------------------*/ 00189 void 00190 elfloader_unload(void) 00191 { 00192 if(elfloader_fini != NULL) { 00193 (*elfloader_fini)(); 00194 elfloader_fini = NULL; 00195 } else if(elfloader_loaded_process != NULL) { 00196 process_exit(elfloader_loaded_process); 00197 elfloader_loaded_process = NULL; 00198 } 00199 if(datamemory != NULL) { 00200 free(datamemory); 00201 datamemory = NULL; 00202 } 00203 }