Contiki 3.x
elfloader-msp430x.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Indian Institute of Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * MSP430x elfloader.
36  * \author
37  * Sumankumar Panchal <suman@ece.iisc.ernet.in>
38  *
39  */
40 
41 #include "contiki.h"
42 #include "loader/elfloader.h"
43 #include "loader/elfloader-arch.h"
44 #include "cfs/cfs.h"
45 #include "loader/symtab.h"
46 #include <stddef.h>
47 #include <string.h>
48 #include <stdio.h>
49 #include "dev/flash.h"
50 
51 #define DEBUG 0
52 #if DEBUG
53 #include <stdio.h>
54 #define PRINTF(...) printf(__VA_ARGS__)
55 #else
56 #define PRINTF(...) do {} while(0)
57 #endif
58 
59 #define EI_NIDENT 16
60 
61 struct elf32_ehdr {
62  unsigned char e_ident[EI_NIDENT]; /* ident bytes */
63  elf32_half e_type; /* file type */
64  elf32_half e_machine; /* target machine */
65  elf32_word e_version; /* file version */
66  elf32_addr e_entry; /* start address */
67  elf32_off e_phoff; /* phdr file offset */
68  elf32_off e_shoff; /* shdr file offset */
69  elf32_word e_flags; /* file flags */
70  elf32_half e_ehsize; /* sizeof ehdr */
71  elf32_half e_phentsize; /* sizeof phdr */
72  elf32_half e_phnum; /* number phdrs */
73  elf32_half e_shentsize; /* sizeof shdr */
74  elf32_half e_shnum; /* number shdrs */
75  elf32_half e_shstrndx; /* shdr string index */
76 };
77 
78 /* Values for e_type. */
79 #define ET_NONE 0 /* Unknown type. */
80 #define ET_REL 1 /* Relocatable. */
81 #define ET_EXEC 2 /* Executable. */
82 #define ET_DYN 3 /* Shared object. */
83 #define ET_CORE 4 /* Core file. */
84 
85 struct elf32_shdr {
86  elf32_word sh_name; /* section name */
87  elf32_word sh_type; /* SHT_... */
88  elf32_word sh_flags; /* SHF_... */
89  elf32_addr sh_addr; /* virtual address */
90  elf32_off sh_offset; /* file offset */
91  elf32_word sh_size; /* section size */
92  elf32_word sh_link; /* misc info */
93  elf32_word sh_info; /* misc info */
94  elf32_word sh_addralign; /* memory alignment */
95  elf32_word sh_entsize; /* entry size if table */
96 };
97 
98 /* sh_type */
99 #define SHT_NULL 0 /* inactive */
100 #define SHT_PROGBITS 1 /* program defined information */
101 #define SHT_SYMTAB 2 /* symbol table section */
102 #define SHT_STRTAB 3 /* string table section */
103 #define SHT_RELA 4 /* relocation section with addends*/
104 #define SHT_HASH 5 /* symbol hash table section */
105 #define SHT_DYNAMIC 6 /* dynamic section */
106 #define SHT_NOTE 7 /* note section */
107 #define SHT_NOBITS 8 /* no space section */
108 #define SHT_REL 9 /* relation section without addends */
109 #define SHT_SHLIB 10 /* reserved - purpose unknown */
110 #define SHT_DYNSYM 11 /* dynamic symbol table section */
111 #define SHT_LOPROC 0x70000000 /* reserved range for processor */
112 #define SHT_HIPROC 0x7fffffff /* specific section header types */
113 #define SHT_LOUSER 0x80000000 /* reserved range for application */
114 #define SHT_HIUSER 0xffffffff /* specific indexes */
115 
116 struct elf32_rel {
117  elf32_addr r_offset; /* Location to be relocated. */
118  elf32_word r_info; /* Relocation type and symbol index. */
119 };
120 
121 struct elf32_sym {
122  elf32_word st_name; /* String table index of name. */
123  elf32_addr st_value; /* Symbol value. */
124  elf32_word st_size; /* Size of associated object. */
125  unsigned char st_info; /* Type and binding information. */
126  unsigned char st_other; /* Reserved (not used). */
127  elf32_half st_shndx; /* Section index of symbol. */
128 };
129 
130 #define ELF32_R_SYM(info) ((info) >> 8)
131 
132 struct relevant_section {
133  unsigned char number;
134  unsigned int offset;
135  char *address;
136 };
137 
138 char elfloader_unknown[30]; /* Name that caused link error. */
139 
140 struct process *const *elfloader_autostart_processes;
141 
142 static struct relevant_section bss, data, rodata, rodatafar, text, textfar;
143 
144 static const unsigned char elf_magic_header[] =
145 { 0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
146  0x01, /* Only 32-bit objects. */
147  0x01, /* Only LSB data. */
148  0x01, /* Only ELF version 1. */
149 };
150 
151 /* relocation type */
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
181 
182 #define ELF32_R_TYPE(info) ((unsigned char)(info))
183 
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 };
188 #else /* ELFLOADER_CONF_TEXT_IN_ROM */
189 static char textmemory[ELFLOADER_TEXTMEMORY_SIZE];
190 #endif /* ELFLOADER_CONF_TEXT_IN_ROM */
191 
192 /*---------------------------------------------------------------------------*/
193 static void
194 seek_read(int fd, unsigned int offset, char *buf, int len)
195 {
196  cfs_seek(fd, offset, CFS_SEEK_SET);
197  cfs_read(fd, buf, len);
198 #if DEBUG
199  {
200  int i;
201  PRINTF("seek_read: Read len %d from offset %d\n",
202  len, offset);
203  for(i = 0; i < len; ++i) {
204  PRINTF("%02x ", buf[i]);
205  }
206  printf("\n");
207  }
208 #endif /* DEBUG */
209 }
210 /*---------------------------------------------------------------------------*/
211 static void *
212 find_local_symbol(int fd, const char *symbol,
213  unsigned int symtab, unsigned short symtabsize,
214  unsigned int strtab)
215 {
216  struct elf32_sym s;
217  unsigned int a;
218  char name[30];
219  struct relevant_section *sect;
220 
221  for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
222  seek_read(fd, a, (char *)&s, sizeof(s));
223  if(s.st_name != 0) {
224  seek_read(fd, strtab + s.st_name, name, sizeof(name));
225  if(strcmp(name, symbol) == 0) {
226  if(s.st_shndx == bss.number) {
227  sect = &bss;
228  } else if(s.st_shndx == data.number) {
229  sect = &data;
230  } else if(s.st_shndx == rodatafar.number) {
231  sect = &rodatafar;
232  } else if(s.st_shndx == textfar.number) {
233  sect = &textfar;
234  } else {
235  return NULL;
236  }
237  return &(sect->address[s.st_value]);
238  }
239  }
240  }
241  return NULL;
242 }
243 /*---------------------------------------------------------------------------*/
244 static int
245 relocate_section(int fd,
246  unsigned int section, unsigned short size,
247  unsigned int sectionaddr,
248  char *sectionbase,
249  unsigned int strs,
250  unsigned int strtab,
251  unsigned int symtab, unsigned short symtabsize,
252  unsigned char using_relas)
253 {
254  /*
255  * sectionbase added; runtime start address of current section
256  */
257  struct elf32_rela rela; /* Now used both for rel and rela data! */
258  int rel_size = 0;
259  struct elf32_sym s;
260  unsigned int a;
261  char name[30];
262  char *addr;
263  struct relevant_section *sect;
264 
265  /* determine correct relocation entry sizes */
266  if(using_relas) {
267  rel_size = sizeof(struct elf32_rela);
268  } else {
269  rel_size = sizeof(struct elf32_rel);
270  }
271 
272  for(a = section; a < section + size; a += rel_size) {
273  seek_read(fd, a, (char *)&rela, rel_size);
274  seek_read(fd,
275  symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
276  (char *)&s, sizeof(s));
277  if(s.st_name != 0) {
278  seek_read(fd, strtab + s.st_name, name, sizeof(name));
279  PRINTF("name: %s\n", name);
280  addr = (char *)symtab_lookup(name);
281  if(addr == NULL) {
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);
285  }
286  if(addr == NULL) {
287  if(s.st_shndx == bss.number) {
288  sect = &bss;
289  } else if(s.st_shndx == data.number) {
290  sect = &data;
291  } else if(s.st_shndx == rodatafar.number) {
292  sect = &rodatafar;
293  } else if(s.st_shndx == textfar.number) {
294  sect = &textfar;
295  } else {
296  PRINTF("elfloader unknown name: '%30s'\n", name);
297  memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
298  elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
300  }
301 
302  addr = sect->address;
303  }
304  } else {
305  if(s.st_shndx == bss.number) {
306  sect = &bss;
307  } else if(s.st_shndx == data.number) {
308  sect = &data;
309  } else if(s.st_shndx == rodatafar.number) {
310  sect = &rodatafar;
311  } else if(s.st_shndx == textfar.number) {
312  sect = &textfar;
313  } else {
315  }
316 
317  addr = sect->address;
318  }
319 
320  if(!using_relas) {
321  /* copy addend to rela structure */
322  seek_read(fd, sectionaddr + rela.r_offset, (char *)&rela.r_addend, 4);
323  }
324 
325  elfloader_arch_relocate(fd, sectionaddr, sectionbase, &rela, addr);
326  }
327 
328  return ELFLOADER_OK;
329 }
330 /*---------------------------------------------------------------------------*/
331 static void *
332 find_program_processes(int fd,
333  unsigned int symtab, unsigned short size,
334  unsigned int strtab)
335 {
336  struct elf32_sym s;
337  unsigned int a;
338  char name[30];
339 
340  for(a = symtab; a < symtab + size; a += sizeof(s)) {
341  seek_read(fd, a, (char *)&s, sizeof(s));
342 
343  if(s.st_name != 0) {
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];
347  }
348  }
349  }
350  return NULL;
351 }
352 /*---------------------------------------------------------------------------*/
353 void
355 {
357 }
358 /*---------------------------------------------------------------------------*/
359 int
361 {
362  struct elf32_ehdr ehdr;
363  struct elf32_shdr shdr;
364  struct elf32_shdr strtable;
365  unsigned int strs;
366  unsigned int shdrptr;
367  unsigned int nameptr;
368  char name[17];
369 
370  int i;
371  unsigned short shdrnum, shdrsize;
372 
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,
379  rodatafarrelasize;
380  unsigned short symtaboff = 0, symtabsize;
381  unsigned short strtaboff = 0, strtabsize;
382  unsigned short bsssize = 0;
383 
384  struct process **process;
385  int ret;
386 
387  elfloader_unknown[0] = 0;
388 
389  /* The ELF header is located at the start of the buffer. */
390  seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
391 
392  /* Make sure that we have a correct and compatible ELF header. */
393  if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
394  PRINTF("ELF header problems\n");
396  }
397 
398  /* Grab the section header. */
399  shdrptr = ehdr.e_shoff;
400  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
401 
402  /* Get the size and number of entries of the section header. */
403  shdrsize = ehdr.e_shentsize;
404  shdrnum = ehdr.e_shnum;
405 
406  PRINTF("Section header: size %d num %d\n", shdrsize, shdrnum);
407 
408  /* The string table section: holds the names of the sections. */
409  seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
410  (char *)&strtable, sizeof(strtable));
411 
412  /*
413  * Get a pointer to the actual table of strings. This table holds
414  * the names of the sections, not the names of other symbols in the
415  * file (these are in the sybtam section).
416  */
417  strs = strtable.sh_offset;
418 
419  PRINTF("Strtable offset %d\n", strs);
420 
421  /*
422  * Go through all sections and pick out the relevant ones. The
423  * ".text" and ".far.text" segments holds the actual code from
424  * the ELF file. The ".data" segment contains initialized data.
425  * The ".bss" segment holds the size of the unitialized data segment.
426  * The ".rodata" and ".far.rodata" segments contains constant data.
427  * The ".rela[a].text" and ".rela[a].far.text" segments contains
428  * relocation information for the contents of the ".text" and
429  * ".far.text" segments, respectively. The ".rela[a].rodata" and
430  * ".rela[a].far.rodata" segments contains relocation information
431  * for the contents of the ".rodata" and ".far.rodata" segments,
432  * respectively. The ".rela[a].data" segment contains relocation
433  * information for the contents of the ".data" segment. The ".symtab"
434  * segment contains the symbol table for this file. The ".strtab"
435  * segment points to the actual string names used by the symbol table.
436  *
437  * In addition to grabbing pointers to the relevant sections, we
438  * also save the section number for resolving addresses in the
439  * relocator code.
440  */
441 
442  /*
443  * Initialize the segment sizes to zero so that we can check if
444  * their sections was found in the file or not.
445  */
446  textsize = textfarsize = textrelasize = textfarrelasize =
447  datasize = datarelasize = rodatasize = rodatafarsize =
448  rodatarelasize = rodatafarrelasize = symtabsize = strtabsize = 0;
449 
450  bss.number = data.number = rodata.number = rodatafar.number =
451  text.number = textfar.number = -1;
452 
453  shdrptr = ehdr.e_shoff;
454  for(i = 0; i < shdrnum; ++i) {
455  seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
456 
457  /* The name of the section is contained in the strings table. */
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",
461  shdrptr,
462  strs, shdr.sh_name,
463  (int)shdr.sh_type);
464  /*
465  * Match the name of the section with a predefined set of names
466  * (.text, .far.text, .data, .bss, .rodata, .far.rodata, .rela.text, .rela.far.text,
467  * .rela.data, .rela.rodata, .rela.far.rodata, .symtab, and .strtab).
468  */
469 
470  if(shdr.sh_type == SHT_SYMTAB) {
471  PRINTF("symtab\n");
472  symtaboff = shdr.sh_offset;
473  symtabsize = shdr.sh_size;
474  } else if(shdr.sh_type == SHT_STRTAB) {
475  PRINTF("strtab\n");
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;
481  text.number = i;
482  text.offset = textoff;
483  } else if(strncmp(name, ".far.text", 9) == 0) {
484  textfaroff = shdr.sh_offset;
485  textfarsize = shdr.sh_size;
486  textfar.number = i;
487  textfar.offset = textfaroff;
488  } else if(strncmp(name, ".rel.text", 9) == 0) {
489  using_relas = 0;
490  textrelaoff = shdr.sh_offset;
491  textrelasize = shdr.sh_size;
492  } else if(strncmp(name, ".rela.text", 10) == 0) {
493  using_relas = 1;
494  textrelaoff = shdr.sh_offset;
495  textrelasize = shdr.sh_size;
496  } else if(strncmp(name, ".rela.far.text", 14) == 0) {
497  using_relas = 1;
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;
503  data.number = i;
504  data.offset = dataoff;
505  } else if(strncmp(name, ".rodata", 7) == 0) {
506  /* read-only data handled the same way as regular text section */
507  rodataoff = shdr.sh_offset;
508  rodatasize = shdr.sh_size;
509  rodata.number = i;
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) {
517  /* using elf32_rel instead of rela */
518  using_relas = 0;
519  rodatarelaoff = shdr.sh_offset;
520  rodatarelasize = shdr.sh_size;
521  } else if(strncmp(name, ".rela.rodata", 12) == 0) {
522  using_relas = 1;
523  rodatarelaoff = shdr.sh_offset;
524  rodatarelasize = shdr.sh_size;
525  } else if(strncmp(name, ".rela.far.rodata", 16) == 0) {
526  using_relas = 1;
527  rodatafarrelaoff = shdr.sh_offset;
528  rodatafarrelasize = shdr.sh_size;
529  } else if(strncmp(name, ".rel.data", 9) == 0) {
530  /* using elf32_rel instead of rela */
531  using_relas = 0;
532  datarelaoff = shdr.sh_offset;
533  datarelasize = shdr.sh_size;
534  } else if(strncmp(name, ".rela.data", 10) == 0) {
535  using_relas = 1;
536  datarelaoff = shdr.sh_offset;
537  datarelasize = shdr.sh_size;
538  } else if(strncmp(name, ".bss", 4) == 0) {
539  bsssize = shdr.sh_size;
540  bss.number = i;
541  bss.offset = 0;
542  }
543 
544  /* Move on to the next section header. */
545  shdrptr += shdrsize;
546  }
547  if(symtabsize == 0) {
548  return ELFLOADER_NO_SYMTAB;
549  }
550  if(strtabsize == 0) {
551  return ELFLOADER_NO_STRTAB;
552  }
553  if(textfarsize == 0) {
554  return ELFLOADER_NO_TEXT;
555  }
556 
557  PRINTF("before allocate ram\n");
558  bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
559  data.address = (char *)bss.address + bsssize;
560  PRINTF("before allocate rom\n");
561  textfar.address = (char *)elfloader_arch_allocate_rom(textfarsize + rodatafarsize);
562  rodatafar.address = (char *)textfar.address + textfarsize;
563 
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);
568 
569  /* If we have text segment relocations, we process them. */
570  PRINTF("elfloader: relocate textfar\n");
571  if(textfarrelasize > 0) {
572  ret = relocate_section(fd,
573  textfarrelaoff, textfarrelasize,
574  textfaroff,
575  textfar.address,
576  strs,
577  strtaboff,
578  symtaboff, symtabsize, using_relas);
579  if(ret != ELFLOADER_OK) {
580  return ret;
581  }
582  }
583 
584  /* If we have any rodata segment relocations, we process them too. */
585  PRINTF("elfloader: relocate rodata\n");
586  if(rodatafarrelasize > 0) {
587  ret = relocate_section(fd,
588  rodatafarrelaoff, rodatafarrelasize,
589  rodatafaroff,
590  rodatafar.address,
591  strs,
592  strtaboff,
593  symtaboff, symtabsize, using_relas);
594  if(ret != ELFLOADER_OK) {
595  PRINTF("elfloader: data failed\n");
596  return ret;
597  }
598  }
599 
600  /* If we have any data segment relocations, we process them too. */
601  PRINTF("elfloader: relocate data\n");
602  if(datarelasize > 0) {
603  ret = relocate_section(fd,
604  datarelaoff, datarelasize,
605  dataoff,
606  data.address,
607  strs,
608  strtaboff,
609  symtaboff, symtabsize, using_relas);
610  if(ret != ELFLOADER_OK) {
611  PRINTF("elfloader: data failed\n");
612  return ret;
613  }
614  }
615 
616  /* Write text and rodata segment into flash and data segment into RAM. */
617  elfloader_arch_write_rom(fd, textfaroff, textfarsize, textfar.address);
618  elfloader_arch_write_rom(fd, rodatafaroff, rodatafarsize, rodatafar.address);
619 
620  memset(bss.address, 0, bsssize);
621  seek_read(fd, dataoff, data.address, datasize);
622 
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");
629  return ELFLOADER_OK;
630  } else {
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");
636  }
638  }
639 }
640 /*---------------------------------------------------------------------------*/
641 void *
643 {
644  return datamemory;
645 }
646 /*---------------------------------------------------------------------------*/
647 void *
649 {
650 #if ELFLOADER_CONF_TEXT_IN_ROM
651  /* Return an 512-byte aligned pointer. */
652  return (char *)
653  ((unsigned long)&textmemory[0] & 0xfffffe00) +
654  (((unsigned long)&textmemory[0] & 0x1ff) == 0 ? 0 : 0x200);
655 #else /* ELFLOADER_CONF_TEXT_IN_ROM */
656  return textmemory;
657 #endif /* ELFLOADER_CONF_TEXT_IN_ROM */
658 }
659 /*---------------------------------------------------------------------------*/
660 #define READSIZE 32
661 void
662 elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
663 {
664 #if ELFLOADER_CONF_TEXT_IN_ROM
665  int i;
666  unsigned int ptr;
667  unsigned short *flashptr;
668 
669  flash_setup();
670 
671  flashptr = (unsigned short *)mem;
672 
673  cfs_seek(fd, textoff, CFS_SEEK_SET);
674  for(ptr = 0; ptr < size; ptr += READSIZE) {
675 
676  /* Read data from file into RAM. */
677  cfs_read(fd, (unsigned char *)datamemory, READSIZE);
678 
679  /* Clear flash page on 512 byte boundary. */
680  if((((unsigned short)flashptr) & 0x01ff) == 0) {
681  flash_clear(flashptr);
682  }
683 
684  /*
685  * Burn data from RAM into flash ROM. Flash is burned one 16-bit
686  * word at a time, so we need to be careful when incrementing
687  * pointers. The flashptr is already a short pointer, so
688  * incrementing it by one will actually increment the address by
689  * two.
690  */
691  for(i = 0; i < READSIZE / 2; ++i) {
692  flash_write(flashptr, ((unsigned short *)datamemory)[i]);
693  ++flashptr;
694  }
695  }
696 
697  flash_done();
698 #else /* ELFLOADER_CONF_TEXT_IN_ROM */
699  cfs_seek(fd, textoff, CFS_SEEK_SET);
700  cfs_read(fd, (unsigned char *)mem, size);
701 #endif /* ELFLOADER_CONF_TEXT_IN_ROM */
702 }
703 /*---------------------------------------------------------------------------*/
704 /* Relocate an MSP430X ELF section. */
705 void
706 elfloader_arch_relocate(int fd, unsigned int sectionoffset,
707  char *sectionaddr,
708  struct elf32_rela *rela, char *addr)
709 {
710  unsigned int type;
711  unsigned char instr[2];
712 
713  type = ELF32_R_TYPE(rela->r_info);
714  addr += rela->r_addend;
715 
716  switch(type) {
717  case R_MSP430_16:
718  case R_MSP430_16_PCREL:
719  case R_MSP430_16_BYTE:
720  case R_MSP430_16_PCREL_BYTE:
721  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
722  cfs_write(fd, (char *)&addr, 2);
723  break;
724  case R_MSP430_32:
725  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
726  cfs_write(fd, (char *)&addr, 2);
727  break;
728  case R_MSP430X_S:
729  case R_MSP430X_S_BYTE:
730  /* src(19:16) located at positions 11:8 of opcode */
731  /* src(15:0) located just after opcode */
732  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
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;
736  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
737  cfs_write(fd, instr, 2);
738  cfs_write(fd, (char *)&addr, 2);
739  break;
740  case R_MSP430X_D:
741  case R_MSP430X_PCREL_D:
742  case R_MSP430X_D_BYTE:
743  /* dst(19:16) located at positions 3:0 of opcode */
744  /* dst(15:0) located just after opcode */
745  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
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);
749  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
750  cfs_write(fd, instr, 2);
751  cfs_write(fd, (char *)&addr, 2);
752  break;
753  case R_MSP430X_PCREL_SRC_BYTE:
754  case R_MSP430X_SRC_BYTE:
755  case R_MSP430X_PCREL_SRC:
756  case R_MSP430X_SRC:
757  /* src(19:16) located at positions 10:7 of extension word */
758  /* src(15:0) located just after opcode */
759  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
760  cfs_read(fd, instr, 2);
761  /* 4 most-significant bits */
762  instr[1] = (int)(instr[1]) & 0xf8 | (((long int)addr >> 9) & 0x0780);
763  instr[0] = (int)(instr[0]) & 0x7f | (((long int)addr >> 9) & 0x0780);
764  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
765  cfs_write(fd, instr, 2);
766  /* 16 least-significant bits */
767  cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
768  cfs_write(fd, (char *)&addr, 2);
769  break;
770  case R_MSP430X_DST_BYTE:
771  case R_MSP430X_PCREL_DST_BYTE:
772  case R_MSP430X_DST:
773  case R_MSP430X_PCREL_DST:
774  /* dst(19:16) located at positions 3:0 of extension word */
775  /* dst(15:0) located just after opcode */
776  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
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);
780  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
781  cfs_write(fd, instr, 2);
782  cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
783  cfs_write(fd, (char *)&addr, 2);
784  break;
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:
789  /* dst(19:16) located at positions 3:0 of extension word */
790  /* dst(15:0) located after src(15:0) */
791  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
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);
795  cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
796  cfs_write(fd, instr, 2);
797  cfs_seek(fd, sectionoffset + rela->r_offset + 0x06, CFS_SEEK_SET);
798  cfs_write(fd, (char *)&addr, 2);
799  break;
800  case R_MSP430X_INDXD:
801  case R_MSP430X_PCREL_INDXD:
802  cfs_seek(fd, sectionoffset + rela->r_offset + 0x02, CFS_SEEK_SET);
803  cfs_write(fd, (char *)&addr, 2);
804  break;
805  default:
806  PRINTF("Unknown relocation type!\n");
807  break;
808  }
809 }
810 /*---------------------------------------------------------------------------*/
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.
Definition: flash.c:48
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
#define CFS_SEEK_SET
Specify that cfs_seek() should compute the offset from the beginning of the file. ...
Definition: cfs.h:127
#define ELFLOADER_NO_STRTAB
Return value from elfloader_load() indicating that no string table could be found in the ELF file...
Definition: elfloader.h:98
#define ELFLOADER_NO_SYMTAB
Return value from elfloader_load() indicating that no symbol table could be found in the ELF file...
Definition: elfloader.h:93
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...
Definition: elfloader.h:121
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.
Definition: elfloader.h:83
#define ELFLOADER_BAD_ELF_HEADER
Return value from elfloader_load() indicating that the ELF file had a bad header. ...
Definition: elfloader.h:88
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...
Definition: elfloader.h:103
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.
Definition: flash.c:98
#define ELFLOADER_SYMBOL_NOT_FOUND
Return value from elfloader_load() indicating that a symbol specific symbol could not be found...
Definition: elfloader.h:111
void flash_done(void)
Function that is to be called after flashing is done.
Definition: flash.c:76
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.
Definition: flash.c:86
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.
Definition: elfloader.h:116
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:1057
CFS header 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).