45 #include "loader/symtab.h"
49 #include "dev/flash.h"
54 #define PRINTF(...) printf(__VA_ARGS__)
56 #define PRINTF(...) do {} while(0)
62 unsigned char e_ident[EI_NIDENT];
71 elf32_half e_phentsize;
73 elf32_half e_shentsize;
75 elf32_half e_shstrndx;
94 elf32_word sh_addralign;
95 elf32_word sh_entsize;
100 #define SHT_PROGBITS 1
105 #define SHT_DYNAMIC 6
110 #define SHT_DYNSYM 11
111 #define SHT_LOPROC 0x70000000
112 #define SHT_HIPROC 0x7fffffff
113 #define SHT_LOUSER 0x80000000
114 #define SHT_HIUSER 0xffffffff
125 unsigned char st_info;
126 unsigned char st_other;
130 #define ELF32_R_SYM(info) ((info) >> 8)
132 struct relevant_section {
133 unsigned char number;
142 static struct relevant_section bss, data, rodata, rodatafar, text, textfar;
144 static const unsigned char elf_magic_header[] =
145 { 0x7f, 0x45, 0x4c, 0x46,
152 #define R_MSP430_NONE 0
153 #define R_MSP430_32 1
154 #define R_MSP430_10_PCREL 2
155 #define R_MSP430_16 3
156 #define R_MSP430_16_PCREL 4
157 #define R_MSP430_16_BYTE 5
158 #define R_MSP430_16_PCREL_BYTE 6
159 #define R_MSP430_2X_PCREL 7
160 #define R_MSP430_RL_PCREL 8
161 #define R_MSP430X_SRC_BYTE 9
162 #define R_MSP430X_SRC 10
163 #define R_MSP430X_DST_BYTE 11
164 #define R_MSP430X_DST 12
165 #define R_MSP430X_DST_2ND_BYTE 13
166 #define R_MSP430X_DST_2ND 14
167 #define R_MSP430X_PCREL_SRC_BYTE 15
168 #define R_MSP430X_PCREL_SRC 16
169 #define R_MSP430X_PCREL_DST_BYTE 17
170 #define R_MSP430X_PCREL_DST 18
171 #define R_MSP430X_PCREL_DST_2ND 19
172 #define R_MSP430X_PCREL_DST_2ND_BYTE 20
173 #define R_MSP430X_S_BYTE 21
174 #define R_MSP430X_S 22
175 #define R_MSP430X_D_BYTE 23
176 #define R_MSP430X_D 24
177 #define R_MSP430X_PCREL_D 25
178 #define R_MSP430X_INDXD 26
179 #define R_MSP430X_PCREL_INDXD 27
180 #define R_MSP430_10 28
182 #define ELF32_R_TYPE(info) ((unsigned char)(info))
184 static uint16_t datamemory_aligned[ELFLOADER_DATAMEMORY_SIZE / 2 + 1];
185 static uint8_t *datamemory = (uint8_t *)datamemory_aligned;
186 #if ELFLOADER_CONF_TEXT_IN_ROM
187 static const char textmemory[ELFLOADER_TEXTMEMORY_SIZE] = { 0 };
189 static char textmemory[ELFLOADER_TEXTMEMORY_SIZE];
194 seek_read(
int fd,
unsigned int offset,
char *buf,
int len)
197 cfs_read(fd, buf, len);
201 PRINTF(
"seek_read: Read len %d from offset %d\n",
203 for(i = 0; i < len; ++i) {
204 PRINTF(
"%02x ", buf[i]);
212 find_local_symbol(
int fd,
const char *symbol,
213 unsigned int symtab,
unsigned short symtabsize,
219 struct relevant_section *sect;
221 for(a = symtab; a < symtab + symtabsize; a +=
sizeof(s)) {
222 seek_read(fd, a, (
char *)&s,
sizeof(s));
224 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
225 if(strcmp(name, symbol) == 0) {
226 if(s.st_shndx == bss.number) {
228 }
else if(s.st_shndx == data.number) {
230 }
else if(s.st_shndx == rodatafar.number) {
232 }
else if(s.st_shndx == textfar.number) {
237 return &(sect->address[s.st_value]);
245 relocate_section(
int fd,
246 unsigned int section,
unsigned short size,
247 unsigned int sectionaddr,
251 unsigned int symtab,
unsigned short symtabsize,
252 unsigned char using_relas)
257 struct elf32_rela rela;
263 struct relevant_section *sect;
267 rel_size =
sizeof(
struct elf32_rela);
269 rel_size =
sizeof(
struct elf32_rel);
272 for(a = section; a < section + size; a += rel_size) {
273 seek_read(fd, a, (
char *)&rela, rel_size);
275 symtab +
sizeof(
struct elf32_sym) * ELF32_R_SYM(rela.r_info),
276 (
char *)&s,
sizeof(s));
278 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
279 PRINTF(
"name: %s\n", name);
280 addr = (
char *)symtab_lookup(name);
282 PRINTF(
"name not found in global: %s\n", name);
283 addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
284 PRINTF(
"found address %p\n", addr);
287 if(s.st_shndx == bss.number) {
289 }
else if(s.st_shndx == data.number) {
291 }
else if(s.st_shndx == rodatafar.number) {
293 }
else if(s.st_shndx == textfar.number) {
296 PRINTF(
"elfloader unknown name: '%30s'\n", name);
302 addr = sect->address;
305 if(s.st_shndx == bss.number) {
307 }
else if(s.st_shndx == data.number) {
309 }
else if(s.st_shndx == rodatafar.number) {
311 }
else if(s.st_shndx == textfar.number) {
317 addr = sect->address;
322 seek_read(fd, sectionaddr + rela.r_offset, (
char *)&rela.r_addend, 4);
332 find_program_processes(
int fd,
333 unsigned int symtab,
unsigned short size,
340 for(a = symtab; a < symtab + size; a +=
sizeof(s)) {
341 seek_read(fd, a, (
char *)&s,
sizeof(s));
344 seek_read(fd, strtab + s.st_name, name,
sizeof(name));
345 if(strcmp(name,
"autostart_processes") == 0) {
346 return &data.address[s.st_value];
362 struct elf32_ehdr ehdr;
363 struct elf32_shdr shdr;
364 struct elf32_shdr strtable;
366 unsigned int shdrptr;
367 unsigned int nameptr;
371 unsigned short shdrnum, shdrsize;
373 unsigned char using_relas = -1;
374 unsigned short textoff = 0, textfaroff = 0, textsize, textfarsize,
375 textrelaoff = 0, textrelasize, textfarrelaoff = 0, textfarrelasize;
376 unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
377 unsigned short rodataoff = 0, rodatafaroff = 0, rodatasize, rodatafarsize,
378 rodatarelaoff = 0, rodatarelasize, rodatafarrelaoff = 0,
380 unsigned short symtaboff = 0, symtabsize;
381 unsigned short strtaboff = 0, strtabsize;
382 unsigned short bsssize = 0;
384 struct process **process;
390 seek_read(fd, 0, (
char *)&ehdr,
sizeof(ehdr));
393 if(memcmp(ehdr.e_ident, elf_magic_header,
sizeof(elf_magic_header)) != 0) {
394 PRINTF(
"ELF header problems\n");
399 shdrptr = ehdr.e_shoff;
400 seek_read(fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
403 shdrsize = ehdr.e_shentsize;
404 shdrnum = ehdr.e_shnum;
406 PRINTF(
"Section header: size %d num %d\n", shdrsize, shdrnum);
409 seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
410 (
char *)&strtable,
sizeof(strtable));
417 strs = strtable.sh_offset;
419 PRINTF(
"Strtable offset %d\n", strs);
446 textsize = textfarsize = textrelasize = textfarrelasize =
447 datasize = datarelasize = rodatasize = rodatafarsize =
448 rodatarelasize = rodatafarrelasize = symtabsize = strtabsize = 0;
450 bss.number = data.number = rodata.number = rodatafar.number =
451 text.number = textfar.number = -1;
453 shdrptr = ehdr.e_shoff;
454 for(i = 0; i < shdrnum; ++i) {
455 seek_read(fd, shdrptr, (
char *)&shdr,
sizeof(shdr));
458 nameptr = strs + shdr.sh_name;
459 seek_read(fd, nameptr, name,
sizeof(name));
460 PRINTF(
"Section shdrptr 0x%x, %d + %d type %d\n",
470 if(shdr.sh_type == SHT_SYMTAB) {
472 symtaboff = shdr.sh_offset;
473 symtabsize = shdr.sh_size;
474 }
else if(shdr.sh_type == SHT_STRTAB) {
476 strtaboff = shdr.sh_offset;
477 strtabsize = shdr.sh_size;
478 }
else if(strncmp(name,
".text", 5) == 0) {
479 textoff = shdr.sh_offset;
480 textsize = shdr.sh_size;
482 text.offset = textoff;
483 }
else if(strncmp(name,
".far.text", 9) == 0) {
484 textfaroff = shdr.sh_offset;
485 textfarsize = shdr.sh_size;
487 textfar.offset = textfaroff;
488 }
else if(strncmp(name,
".rel.text", 9) == 0) {
490 textrelaoff = shdr.sh_offset;
491 textrelasize = shdr.sh_size;
492 }
else if(strncmp(name,
".rela.text", 10) == 0) {
494 textrelaoff = shdr.sh_offset;
495 textrelasize = shdr.sh_size;
496 }
else if(strncmp(name,
".rela.far.text", 14) == 0) {
498 textfarrelaoff = shdr.sh_offset;
499 textfarrelasize = shdr.sh_size;
500 }
else if(strncmp(name,
".data", 5) == 0) {
501 dataoff = shdr.sh_offset;
502 datasize = shdr.sh_size;
504 data.offset = dataoff;
505 }
else if(strncmp(name,
".rodata", 7) == 0) {
507 rodataoff = shdr.sh_offset;
508 rodatasize = shdr.sh_size;
510 rodata.offset = rodataoff;
511 }
else if(strncmp(name,
".far.rodata", 11) == 0) {
512 rodatafaroff = shdr.sh_offset;
513 rodatafarsize = shdr.sh_size;
514 rodatafar.number = i;
515 rodatafar.offset = rodataoff;
516 }
else if(strncmp(name,
".rel.rodata", 11) == 0) {
519 rodatarelaoff = shdr.sh_offset;
520 rodatarelasize = shdr.sh_size;
521 }
else if(strncmp(name,
".rela.rodata", 12) == 0) {
523 rodatarelaoff = shdr.sh_offset;
524 rodatarelasize = shdr.sh_size;
525 }
else if(strncmp(name,
".rela.far.rodata", 16) == 0) {
527 rodatafarrelaoff = shdr.sh_offset;
528 rodatafarrelasize = shdr.sh_size;
529 }
else if(strncmp(name,
".rel.data", 9) == 0) {
532 datarelaoff = shdr.sh_offset;
533 datarelasize = shdr.sh_size;
534 }
else if(strncmp(name,
".rela.data", 10) == 0) {
536 datarelaoff = shdr.sh_offset;
537 datarelasize = shdr.sh_size;
538 }
else if(strncmp(name,
".bss", 4) == 0) {
539 bsssize = shdr.sh_size;
547 if(symtabsize == 0) {
550 if(strtabsize == 0) {
553 if(textfarsize == 0) {
557 PRINTF(
"before allocate ram\n");
559 data.address = (
char *)bss.address + bsssize;
560 PRINTF(
"before allocate rom\n");
562 rodatafar.address = (
char *)textfar.address + textfarsize;
564 PRINTF(
"bss base address: bss.address = 0x%08x\n", bss.address);
565 PRINTF(
"data base address: data.address = 0x%08x\n", data.address);
566 PRINTF(
"textfar base address: textfar.address = 0x%08x\n", textfar.address);
567 PRINTF(
"rodatafar base address: rodatafar.address = 0x%08x\n", rodatafar.address);
570 PRINTF(
"elfloader: relocate textfar\n");
571 if(textfarrelasize > 0) {
572 ret = relocate_section(fd,
573 textfarrelaoff, textfarrelasize,
578 symtaboff, symtabsize, using_relas);
585 PRINTF(
"elfloader: relocate rodata\n");
586 if(rodatafarrelasize > 0) {
587 ret = relocate_section(fd,
588 rodatafarrelaoff, rodatafarrelasize,
593 symtaboff, symtabsize, using_relas);
595 PRINTF(
"elfloader: data failed\n");
601 PRINTF(
"elfloader: relocate data\n");
602 if(datarelasize > 0) {
603 ret = relocate_section(fd,
604 datarelaoff, datarelasize,
609 symtaboff, symtabsize, using_relas);
611 PRINTF(
"elfloader: data failed\n");
620 memset(bss.address, 0, bsssize);
621 seek_read(fd, dataoff, data.address, datasize);
623 PRINTF(
"elfloader: autostart search\n");
624 process = (
struct process **)find_local_symbol(fd,
"autostart_processes",
625 symtaboff, symtabsize, strtaboff);
626 if(process !=
NULL) {
627 PRINTF(
"elfloader: autostart found\n");
631 PRINTF(
"elfloader: no autostart\n");
632 process = (
struct process **)find_program_processes(fd, symtaboff,
633 symtabsize, strtaboff);
634 if(process !=
NULL) {
635 PRINTF(
"elfloader: FOUND PRG\n");
650 #if ELFLOADER_CONF_TEXT_IN_ROM
653 ((
unsigned long)&textmemory[0] & 0xfffffe00) +
654 (((
unsigned long)&textmemory[0] & 0x1ff) == 0 ? 0 : 0x200);
664 #if ELFLOADER_CONF_TEXT_IN_ROM
667 unsigned short *flashptr;
671 flashptr = (
unsigned short *)mem;
674 for(ptr = 0; ptr < size; ptr += READSIZE) {
677 cfs_read(fd, (
unsigned char *)datamemory, READSIZE);
680 if((((
unsigned short)flashptr) & 0x01ff) == 0) {
691 for(i = 0; i < READSIZE / 2; ++i) {
692 flash_write(flashptr, ((
unsigned short *)datamemory)[i]);
700 cfs_read(fd, (
unsigned char *)mem, size);
708 struct elf32_rela *rela,
char *addr)
711 unsigned char instr[2];
713 type = ELF32_R_TYPE(rela->r_info);
714 addr += rela->r_addend;
718 case R_MSP430_16_PCREL:
719 case R_MSP430_16_BYTE:
720 case R_MSP430_16_PCREL_BYTE:
722 cfs_write(fd, (
char *)&addr, 2);
726 cfs_write(fd, (
char *)&addr, 2);
729 case R_MSP430X_S_BYTE:
733 cfs_read(fd, instr, 2);
734 instr[1] = (int)(instr[1]) & 0xf0 | (((
long int)addr >> 8) & 0x0f00);
735 instr[0] = (int)(instr[0]) & 0xff;
737 cfs_write(fd, instr, 2);
738 cfs_write(fd, (
char *)&addr, 2);
741 case R_MSP430X_PCREL_D:
742 case R_MSP430X_D_BYTE:
746 cfs_read(fd, instr, 2);
747 instr[1] = (int)(instr[1]) & 0xff;
748 instr[0] = (int)(instr[0]) & 0xf0 | (((
long int)addr >> 16) & 0x000f);
750 cfs_write(fd, instr, 2);
751 cfs_write(fd, (
char *)&addr, 2);
753 case R_MSP430X_PCREL_SRC_BYTE:
754 case R_MSP430X_SRC_BYTE:
755 case R_MSP430X_PCREL_SRC:
760 cfs_read(fd, instr, 2);
762 instr[1] = (int)(instr[1]) & 0xf8 | (((
long int)addr >> 9) & 0x0780);
763 instr[0] = (int)(instr[0]) & 0x7f | (((
long int)addr >> 9) & 0x0780);
765 cfs_write(fd, instr, 2);
768 cfs_write(fd, (
char *)&addr, 2);
770 case R_MSP430X_DST_BYTE:
771 case R_MSP430X_PCREL_DST_BYTE:
773 case R_MSP430X_PCREL_DST:
777 cfs_read(fd, instr, 2);
778 instr[1] = (int)(instr[1]) & 0xff;
779 instr[0] = (int)(instr[0]) & 0xf0 | (((
long int)addr >> 16) & 0x000f);
781 cfs_write(fd, instr, 2);
783 cfs_write(fd, (
char *)&addr, 2);
785 case R_MSP430X_DST_2ND:
786 case R_MSP430X_PCREL_DST_2ND:
787 case R_MSP430X_DST_2ND_BYTE:
788 case R_MSP430X_PCREL_DST_2ND_BYTE:
792 cfs_read(fd, instr, 2);
793 instr[1] = (int)(instr[1]) & 0xff;
794 instr[0] = (int)(instr[0]) & 0xf0 | (((
long int)addr >> 16) & 0x000f);
796 cfs_write(fd, instr, 2);
798 cfs_write(fd, (
char *)&addr, 2);
800 case R_MSP430X_INDXD:
801 case R_MSP430X_PCREL_INDXD:
803 cfs_write(fd, (
char *)&addr, 2);
806 PRINTF(
"Unknown relocation type!\n");
char elfloader_unknown[30]
If elfloader_load() could not find a specific symbol, it is copied into this array.
void flash_setup(void)
Setup function to be called before any of the flash programming functions.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
#define ELFLOADER_NO_STRTAB
Return value from elfloader_load() indicating that no string table could be found in the ELF file...
#define ELFLOADER_NO_SYMTAB
Return value from elfloader_load() indicating that no symbol table could be found in the ELF file...
Header file for the Contiki ELF loader.
#define ELFLOADER_NO_STARTPOINT
Return value from elfloader_load() indicating that no starting point could be found in the loaded mod...
void * elfloader_arch_allocate_rom(int size)
Allocate program memory for a new module.
void elfloader_init(void)
elfloader initialization function.
#define ELFLOADER_OK
Return value from elfloader_load() indicating that loading worked.
#define ELFLOADER_BAD_ELF_HEADER
Return value from elfloader_load() indicating that the ELF file had a bad header. ...
struct process *const * elfloader_autostart_processes
A pointer to the processes loaded with elfloader_load().
#define NULL
The null pointer.
#define ELFLOADER_NO_TEXT
Return value from elfloader_load() indicating that the size of the .text segment was zero...
void elfloader_arch_relocate(int fd, unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr)
Perform a relocation.
void flash_write(unsigned short *ptr, unsigned short word)
Write a 16-bit word to flash ROM.
#define ELFLOADER_SYMBOL_NOT_FOUND
Return value from elfloader_load() indicating that a symbol specific symbol could not be found...
void flash_done(void)
Function that is to be called after flashing is done.
int elfloader_load(int fd)
Load and relocate an ELF file.
void flash_clear(unsigned short *ptr)
Clear a 16-bit word in flash ROM.
Header file for the architecture specific parts of the Contiki ELF loader.
#define ELFLOADER_SEGMENT_NOT_FOUND
Return value from elfloader_load() indicating that one of the required segments (.data, .bss, or .text) could not be found.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
void * elfloader_arch_allocate_ram(int size)
Allocate RAM for a new module.
void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
Write to read-only memory (for example the text segment).