4 Loads a .elf file, extract the code, the data, the eeprom and
5 the "mcu" specification section, also load usable code symbols
6 to be able to print meaningful trace information.
8 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
10 This file is part of simavr.
12 simavr is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
17 simavr is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with simavr. If not, see <http://www.gnu.org/licenses/>.
36 #include "avr_eeprom.h"
38 void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
40 avr->frequency = firmware->mmcu.f_cpu;
41 #if CONFIG_SIMAVR_TRACE
42 avr->codeline = firmware->codeline;
44 avr_loadcode(avr, firmware->flash, firmware->flashsize, 0);
45 avr->codeend = firmware->flashsize - firmware->datasize;
46 if (firmware->eeprom && firmware->eesize) {
47 avr_eeprom_desc_t d = { .ee = firmware->eeprom, .offset = 0, .size = firmware->eesize };
48 avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d);
52 int elf_read_firmware(const char * file, elf_firmware_t * firmware)
54 Elf32_Ehdr elf_header; /* ELF header */
55 Elf *elf = NULL; /* Our Elf pointer for libelf */
56 int fd; // File Descriptor
58 if ((fd = open(file, O_RDONLY)) == -1 ||
59 (read(fd, &elf_header, sizeof(elf_header))) < sizeof(elf_header)) {
60 printf("could not read %s\n", file);
66 Elf_Data *data_data = NULL,
68 *data_ee = NULL; /* Data Descriptor */
70 memset(firmware, 0, sizeof(*firmware));
72 //int bitesize = ((avr->flashend+1) >> 1) * sizeof(avr_symbol_t);
73 firmware->codesize = 32768;
74 int bitesize = firmware->codesize * sizeof(avr_symbol_t);
75 firmware->codeline = malloc(bitesize);
76 memset(firmware->codeline,0, bitesize);
79 /* this is actualy mandatory !! otherwise elf_begin() fails */
80 if (elf_version(EV_CURRENT) == EV_NONE) {
81 /* library out of date - recover from error */
83 // Iterate through section headers again this time well stop when we find symbols
84 elf = elf_begin(fd, ELF_C_READ, NULL);
85 //printf("Loading elf %s : %p\n", file, elf);
87 Elf_Scn *scn = NULL; /* Section Descriptor */
89 while ((scn = elf_nextscn(elf, scn)) != NULL) {
90 GElf_Shdr shdr; /* Section Header */
91 gelf_getshdr(scn, &shdr);
92 char * name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name);
93 // printf("Walking elf section '%s'\n", name);
95 if (!strcmp(name, ".text"))
96 data_text = elf_getdata(scn, NULL);
97 else if (!strcmp(name, ".data"))
98 data_data = elf_getdata(scn, NULL);
99 else if (!strcmp(name, ".eeprom"))
100 data_ee = elf_getdata(scn, NULL);
101 else if (!strcmp(name, ".bss")) {
102 Elf_Data *s = elf_getdata(scn, NULL);
103 firmware->bsssize = s->d_size;
104 } else if (!strcmp(name, ".mmcu")) {
105 Elf_Data *s = elf_getdata(scn, NULL);
106 firmware->mmcu = *((struct avr_mcu_t*)s->d_buf);
107 //printf("%s: avr_mcu_t size %ld / read %ld\n", __FUNCTION__, sizeof(struct avr_mcu_t), s->d_size);
108 // avr->frequency = f_cpu;
111 // When we find a section header marked SHT_SYMTAB stop and get symbols
112 if (shdr.sh_type == SHT_SYMTAB) {
113 // edata points to our symbol table
114 Elf_Data *edata = elf_getdata(scn, NULL);
116 // how many symbols are there? this number comes from the size of
117 // the section divided by the entry size
118 int symbol_count = shdr.sh_size / shdr.sh_entsize;
120 // loop through to grab all symbols
121 for (int i = 0; i < symbol_count; i++) {
122 GElf_Sym sym; /* Symbol */
123 // libelf grabs the symbol data using gelf_getsym()
124 gelf_getsym(edata, i, &sym);
126 // print out the value and size
127 // printf("%08x %08d ", sym.st_value, sym.st_size);
128 if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL ||
129 ELF32_ST_TYPE(sym.st_info) == STT_FUNC ||
130 ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) {
131 const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name);
134 if (sym.st_value & 0xfff00000) {
138 if (firmware->codeline[sym.st_value >> 1] == NULL) {
139 avr_symbol_t * s = firmware->codeline[sym.st_value >> 1] = malloc(sizeof(avr_symbol_t*));
140 s->symbol = strdup(name);
141 s->addr = sym.st_value;
150 avr_symbol_t * last = NULL;
151 for (int i = 0; i < firmware->codesize; i++) {
152 if (!firmware->codeline[i])
153 firmware->codeline[i] = last;
155 last = firmware->codeline[i];
159 firmware->flashsize =
160 (data_text ? data_text->d_size : 0) +
161 (data_data ? data_data->d_size : 0);
162 firmware->flash = malloc(firmware->flashsize);
164 // hdump("code", data_text->d_buf, data_text->d_size);
165 memcpy(firmware->flash + offset, data_text->d_buf, data_text->d_size);
166 offset += data_text->d_size;
167 printf("Loaded %d .text\n", data_text->d_size);
170 // hdump("data", data_data->d_buf, data_data->d_size);
171 memcpy(firmware->flash + offset, data_data->d_buf, data_data->d_size);
172 printf("Loaded %d .data\n", data_data->d_size);
173 offset += data_data->d_size;
174 firmware->datasize = data_data->d_size;
177 // hdump("eeprom", data_ee->d_buf, data_ee->d_size);
178 firmware->eeprom = malloc(data_ee->d_size);
179 memcpy(firmware->eeprom, data_ee->d_buf, data_ee->d_size);
180 printf("Loaded %d .eeprom\n", data_ee->d_size);
181 firmware->eesize = data_ee->d_size;
183 // hdump("flash", avr->flash, offset);