Contiki 2.5
elfloader-arch.c
1 #include "contiki.h"
2 #include "elfloader-arch.h"
3 #include "cfs-coffee-arch.h"
4 
5 #if 1
6 #include <stdio.h>
7 #define PRINTF(...) printf(__VA_ARGS__)
8 #else
9 #define PRINTF(...) do {} while (0)
10 #endif
11 
12 #define ELF32_R_TYPE(info) ((unsigned char)(info))
13 
14 /* Supported relocations */
15 
16 #define R_ARM_ABS32 2
17 #define R_ARM_THM_CALL 10
18 
19 /* Adapted from elfloader-arm.c */
20 
21 static uint32_t datamemory_aligned[(ELFLOADER_DATAMEMORY_SIZE+3)/4]; //word aligned
22 static uint8_t* datamemory = (uint8_t *)datamemory_aligned;
23 VAR_AT_SEGMENT (static const uint16_t textmemory[ELFLOADER_TEXTMEMORY_SIZE/2],".elf_text") = {0}; //halfword aligned
24 /*---------------------------------------------------------------------------*/
25 void *
27 {
28  if(size > sizeof(datamemory_aligned)){
29  PRINTF("RESERVED RAM TOO SMALL\n");
30  }
31  return datamemory;
32 }
33 /*---------------------------------------------------------------------------*/
34 void *
36 {
37  if(size > sizeof(textmemory)){
38  PRINTF("RESERVED FLASH TOO SMALL\n");
39  }
40  return (void *)textmemory;
41 }
42 /*---------------------------------------------------------------------------*/
43 #define READSIZE sizeof(datamemory_aligned)
44 
45 void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
46 {
47  int32u ptr;
48  int nbytes;
49 
50  cfs_seek(fd, textoff, CFS_SEEK_SET);
51 
52  cfs_seek(fd, textoff, CFS_SEEK_SET);
53  for(ptr = 0; ptr < size; ptr += READSIZE) {
54 
55  /* Read data from file into RAM. */
56  nbytes = cfs_read(fd, (unsigned char *)datamemory, READSIZE);
57 
58  /* Write data to flash. */
59  stm32w_flash_write((int32u)mem, datamemory, nbytes);
60  }
61 }
62 /*---------------------------------------------------------------------------*/
63 
64 
66  unsigned int sectionoffset,
67  char *sectionaddr,
68  struct elf32_rela *rela, char *addr)
69 {
70  unsigned int type;
71 
72  type = ELF32_R_TYPE(rela->r_info);
73 
74  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
75 
76 /* PRINTF("elfloader_arch_relocate: type %d\n", type); */
77 /* PRINTF("Addr: %p, Addend: %ld\n", addr, rela->r_addend); */
78  switch(type) {
79  case R_ARM_ABS32:
80  {
81  int32_t addend;
82  cfs_read(fd, (char*)&addend, 4);
83  addr += addend;
84  cfs_seek(fd, -4, CFS_SEEK_CUR);
85  cfs_write(fd,&addr,4);
86  //elfloader_output_write_segment(output,(char*) &addr, 4);
87  PRINTF("%p: addr: %p\n", sectionaddr +rela->r_offset,
88  addr);
89  }
90  break;
91  case R_ARM_THM_CALL:
92  {
93  uint16_t instr[2];
94  int32_t offset;
95  char *base;
96  cfs_read(fd, (char*)instr, 4);
97  cfs_seek(fd, -4, CFS_SEEK_CUR);
98  /* Ignore the addend since it will be zero for calls to symbols,
99  and I can't think of a case when doing a relative call to
100  a non-symbol position */
101  base = sectionaddr + (rela->r_offset + 4);
102 
103  if (((instr[1]) & 0xe800) == 0xe800) {
104  /* BL or BLX */
105  if (((uint32_t)addr) & 0x1) {
106  /* BL */
107  instr[1] |= 0x1800;
108  } else {
109 #if defined(__ARM_ARCH_4T__)
111 #else
112  /* BLX */
113  instr[1] &= ~0x1800;
114  instr[1] |= 0x0800;
115 #endif
116  }
117  }
118  /* Adjust address for BLX */
119  if ((instr[1] & 0x1800) == 0x0800) {
120  addr = (char*)((((uint32_t)addr) & 0xfffffffd)
121  | (((uint32_t)base) & 0x00000002));
122  }
123  offset = addr - (sectionaddr + (rela->r_offset + 4));
124  PRINTF("elfloader-arm.c: offset %d\n", (int)offset);
125  if (offset < -(1<<22) || offset >= (1<<22)) {
126  PRINTF("elfloader-arm.c: offset %d too large for relative call\n",
127  (int)offset);
128  }
129  /* PRINTF("%p: %04x %04x offset: %d addr: %p\n", sectionaddr +rela->r_offset, instr[0], instr[1], (int)offset, addr); */
130  instr[0] = (instr[0] & 0xf800) | ((offset>>12)&0x07ff);
131  instr[1] = (instr[1] & 0xf800) | ((offset>>1)&0x07ff);
132  cfs_write(fd,&instr,4);
133  //elfloader_output_write_segment(output, (char*)instr, 4);
134  /* PRINTF("cfs_write: %04x %04x\n",instr[0], instr[1]); */
135  }
136  break;
137 
138  default:
139  PRINTF("elfloader-arm.c: unsupported relocation type %d\n", type);
140  }
141 }