Contiki 3.x
elfloader-arch.c
1 /**
2  * \addtogroup mbxxx-platform
3  *
4  * @{
5  */
6 
7 /*
8  * Copyright (c) 2009, Swedish Institute of Computer Science
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the Institute nor the names of its contributors
20  * may be used to endorse or promote products derived from this software
21  * without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 #include "contiki.h"
38 #include "elfloader-arch.h"
39 #include "cfs-coffee-arch.h"
40 
41 #if 1
42 #include <stdio.h>
43 #define PRINTF(...) printf(__VA_ARGS__)
44 #else
45 #define PRINTF(...) do {} while (0)
46 #endif
47 
48 #define ELF32_R_TYPE(info) ((unsigned char)(info))
49 
50 /* Supported relocations */
51 #define R_ARM_ABS32 2
52 #define R_ARM_THM_CALL 10
53 
54 /* Adapted from elfloader-arm.c */
55 /* word aligned */
56 static uint32_t datamemory_aligned[(ELFLOADER_DATAMEMORY_SIZE + 3) / 4];
57 static uint8_t *datamemory = (uint8_t *) datamemory_aligned;
58 
59 /* halfword aligned */
60 VAR_AT_SEGMENT(static const uint16_t
61  textmemory[ELFLOADER_TEXTMEMORY_SIZE / 2], ".elf_text") = {0};
62 /*---------------------------------------------------------------------------*/
63 void *
65 {
66  if(size > sizeof(datamemory_aligned)) {
67  PRINTF("RESERVED RAM TOO SMALL\n");
68  }
69  return datamemory;
70 }
71 /*---------------------------------------------------------------------------*/
72 void *
74 {
75  if(size > sizeof(textmemory)) {
76  PRINTF("RESERVED FLASH TOO SMALL\n");
77  }
78  return (void *)textmemory;
79 }
80 /*---------------------------------------------------------------------------*/
81 #define READSIZE sizeof(datamemory_aligned)
82 
83 void
84 elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size,
85  char *mem)
86 {
87  uint32_t ptr;
88  int nbytes;
89  cfs_seek(fd, textoff, CFS_SEEK_SET);
90  cfs_seek(fd, textoff, CFS_SEEK_SET);
91  for(ptr = 0; ptr < size; ptr += READSIZE) {
92  /* Read data from file into RAM. */
93  nbytes = cfs_read(fd, (unsigned char *)datamemory, READSIZE);
94  /* Write data to flash. */
95  stm32w_flash_write((uint32_t) mem, datamemory, nbytes);
96  }
97 }
98 /*---------------------------------------------------------------------------*/
99 void
101  unsigned int sectionoffset,
102  char *sectionaddr,
103  struct elf32_rela *rela, char *addr)
104 {
105  unsigned int type;
106  type = ELF32_R_TYPE(rela->r_info);
107  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
108 /* PRINTF("elfloader_arch_relocate: type %d\n", type); */
109 /* PRINTF("Addr: %p, Addend: %ld\n", addr, rela->r_addend); */
110  switch (type) {
111  case R_ARM_ABS32:
112  {
113  int32_t addend;
114  cfs_read(fd, (char *)&addend, 4);
115  addr += addend;
116  cfs_seek(fd, -4, CFS_SEEK_CUR);
117  cfs_write(fd, &addr, 4);
118  /* elfloader_output_write_segment(output,(char*) &addr, 4); */
119  PRINTF("%p: addr: %p\n", sectionaddr + rela->r_offset, addr);
120  }
121  break;
122  case R_ARM_THM_CALL:
123  {
124  uint16_t instr[2];
125  int32_t offset;
126  char *base;
127  cfs_read(fd, (char *)instr, 4);
128  cfs_seek(fd, -4, CFS_SEEK_CUR);
129 
130  /*
131  * Ignore the addend since it will be zero for calls to symbols,
132  * and I can't think of a case when doing a relative call to
133  * a non-symbol position
134  */
135  base = sectionaddr + (rela->r_offset + 4);
136  if(((instr[1]) & 0xe800) == 0xe800) {
137  /* BL or BLX */
138  if(((uint32_t) addr) & 0x1) {
139  /* BL */
140  instr[1] |= 0x1800;
141  } else {
142 #if defined(__ARM_ARCH_4T__)
144 #else
145  /* BLX */
146  instr[1] &= ~0x1800;
147  instr[1] |= 0x0800;
148 #endif
149  }
150  }
151 
152  /* Adjust address for BLX */
153  if((instr[1] & 0x1800) == 0x0800) {
154  addr = (char *)((((uint32_t) addr) & 0xfffffffd) |
155  (((uint32_t) base) & 0x00000002));
156  }
157  offset = addr - (sectionaddr + (rela->r_offset + 4));
158  PRINTF("elfloader-arm.c: offset %d\n", (int)offset);
159  if(offset < -(1 << 22) || offset >= (1 << 22)) {
160  PRINTF("elfloader-arm.c: offset %d too large for relative call\n",
161  (int)offset);
162  }
163  /* PRINTF("%p: %04x %04x offset: %d addr: %p\n", sectionaddr +rela->r_offset, instr[0], instr[1], (int)offset, addr); */
164  instr[0] = (instr[0] & 0xf800) | ((offset >> 12) & 0x07ff);
165  instr[1] = (instr[1] & 0xf800) | ((offset >> 1) & 0x07ff);
166  cfs_write(fd, &instr, 4);
167  /* elfloader_output_write_segment(output, (char*)instr, 4); */
168  /* PRINTF("cfs_write: %04x %04x\n",instr[0], instr[1]); */
169  }
170  break;
171 
172  default:
173  PRINTF("elfloader-arm.c: unsupported relocation type %d\n", type);
174  }
175 }
176 /** @} */
void elfloader_arch_relocate(int fd, unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr)
Perform a relocation.
cfs_offset_t cfs_seek(int fd, cfs_offset_t offset, int whence)
Seek to a specified position in an open file.
Definition: cfs-coffee.c:1042
#define CFS_SEEK_CUR
Specify that cfs_seek() should compute the offset from the current position of the file pointer...
Definition: cfs.h:136
Header file for the architecture specific parts of the Contiki ELF loader.
#define VAR_AT_SEGMENT(__variableDeclaration, __segmentName)
Provide a portable way to specify the segment where a variable lives.
Definition: gnu.h:274
void * elfloader_arch_allocate_ram(int size)
Allocate RAM for a new module.
Definition: elfloader-avr.c:74
#define ELFLOADER_UNHANDLED_RELOC
Return value from elfloader_load() indicating that the ELF file contained a relocation type that the ...
Coffee architecture-dependent header for the STM32W108-based mb851 platform.
void * elfloader_arch_allocate_rom(int size)
Allocate program memory for a new module.
Definition: elfloader-avr.c:95
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
Definition: cfs.h:127
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).