elfloader-arch.c
00001 #include "contiki.h"
00002 #include "elfloader-arch.h"
00003 #include "cfs-coffee-arch.h"
00004
00005 #if 1
00006 #include <stdio.h>
00007 #define PRINTF(...) printf(__VA_ARGS__)
00008 #else
00009 #define PRINTF(...) do {} while (0)
00010 #endif
00011
00012 #define ELF32_R_TYPE(info) ((unsigned char)(info))
00013
00014
00015
00016 #define R_ARM_ABS32 2
00017 #define R_ARM_THM_CALL 10
00018
00019
00020
00021 static uint32_t datamemory_aligned[(ELFLOADER_DATAMEMORY_SIZE+3)/4];
00022 static uint8_t* datamemory = (uint8_t *)datamemory_aligned;
00023 VAR_AT_SEGMENT (static const uint16_t textmemory[ELFLOADER_TEXTMEMORY_SIZE/2],".elf_text") = {0};
00024
00025 void *
00026 elfloader_arch_allocate_ram(int size)
00027 {
00028 if(size > sizeof(datamemory_aligned)){
00029 PRINTF("RESERVED RAM TOO SMALL\n");
00030 }
00031 return datamemory;
00032 }
00033
00034 void *
00035 elfloader_arch_allocate_rom(int size)
00036 {
00037 if(size > sizeof(textmemory)){
00038 PRINTF("RESERVED FLASH TOO SMALL\n");
00039 }
00040 return (void *)textmemory;
00041 }
00042
00043 #define READSIZE sizeof(datamemory_aligned)
00044
00045 void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
00046 {
00047 int32u ptr;
00048 int nbytes;
00049
00050 cfs_seek(fd, textoff, CFS_SEEK_SET);
00051
00052 cfs_seek(fd, textoff, CFS_SEEK_SET);
00053 for(ptr = 0; ptr < size; ptr += READSIZE) {
00054
00055
00056 nbytes = cfs_read(fd, (unsigned char *)datamemory, READSIZE);
00057
00058
00059 stm32w_flash_write((int32u)mem, datamemory, nbytes);
00060 }
00061 }
00062
00063
00064
00065 void elfloader_arch_relocate(int fd,
00066 unsigned int sectionoffset,
00067 char *sectionaddr,
00068 struct elf32_rela *rela, char *addr)
00069 {
00070 unsigned int type;
00071
00072 type = ELF32_R_TYPE(rela->r_info);
00073
00074 cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
00075
00076
00077
00078 switch(type) {
00079 case R_ARM_ABS32:
00080 {
00081 int32_t addend;
00082 cfs_read(fd, (char*)&addend, 4);
00083 addr += addend;
00084 cfs_seek(fd, -4, CFS_SEEK_CUR);
00085 cfs_write(fd,&addr,4);
00086
00087 PRINTF("%p: addr: %p\n", sectionaddr +rela->r_offset,
00088 addr);
00089 }
00090 break;
00091 case R_ARM_THM_CALL:
00092 {
00093 uint16_t instr[2];
00094 int32_t offset;
00095 char *base;
00096 cfs_read(fd, (char*)instr, 4);
00097 cfs_seek(fd, -4, CFS_SEEK_CUR);
00098
00099
00100
00101 base = sectionaddr + (rela->r_offset + 4);
00102
00103 if (((instr[1]) & 0xe800) == 0xe800) {
00104
00105 if (((uint32_t)addr) & 0x1) {
00106
00107 instr[1] |= 0x1800;
00108 } else {
00109 #if defined(__ARM_ARCH_4T__)
00110 return ELFLOADER_UNHANDLED_RELOC;
00111 #else
00112
00113 instr[1] &= ~0x1800;
00114 instr[1] |= 0x0800;
00115 #endif
00116 }
00117 }
00118
00119 if ((instr[1] & 0x1800) == 0x0800) {
00120 addr = (char*)((((uint32_t)addr) & 0xfffffffd)
00121 | (((uint32_t)base) & 0x00000002));
00122 }
00123 offset = addr - (sectionaddr + (rela->r_offset + 4));
00124 PRINTF("elfloader-arm.c: offset %d\n", (int)offset);
00125 if (offset < -(1<<22) || offset >= (1<<22)) {
00126 PRINTF("elfloader-arm.c: offset %d too large for relative call\n",
00127 (int)offset);
00128 }
00129
00130 instr[0] = (instr[0] & 0xf800) | ((offset>>12)&0x07ff);
00131 instr[1] = (instr[1] & 0xf800) | ((offset>>1)&0x07ff);
00132 cfs_write(fd,&instr,4);
00133
00134
00135 }
00136 break;
00137
00138 default:
00139 PRINTF("elfloader-arm.c: unsupported relocation type %d\n", type);
00140 }
00141 }