00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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];
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
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
00108
00109 datamemory = malloc(IMAX(h.textsize, h.datasize + h.bsssize));
00110 if(datamemory == NULL) {
00111 return ELFLOADER_DATA_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
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 }