From 59adc2d64a2b7609962d43c5d9ff39372090f40c Mon Sep 17 00:00:00 2001 From: root Date: Sat, 3 Sep 2022 17:59:49 +0200 Subject: [PATCH 01/10] + Support ELF files with multiple segments that go into flash memory. + Use p_filesz and p_memsz in the ELF header according to the ELF specification. --- simavr/sim/sim_elf.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index df69b8121..5a96418ee 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -276,14 +278,20 @@ static int elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) { int rv; - - if (*dest == NULL) - *dest = malloc(php->p_filesz); + Elf32_Addr segment_end; + + /* Allocate enough memory to load the segment. + Note that both malloc_usable_size and realloc do the right thing in + case *dest==NULL (i.o.w. no memory allocated yet) */ + segment_end = php->p_vaddr + php->p_memsz; + if (malloc_usable_size(*dest) < segment_end) { + *dest = realloc(*dest, segment_end); + } if (!*dest) return -1; lseek(fd, php->p_offset, SEEK_SET); - rv = read(fd, *dest, php->p_filesz); + rv = read(fd, *dest + php->p_vaddr, php->p_filesz); if (rv != php->p_filesz) { AVR_LOG(NULL, LOG_ERROR, "Got %d when reading %d bytes for %x at offset %d " @@ -291,6 +299,11 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) rv, php->p_filesz, php->p_vaddr, php->p_offset); return -1; } + /* ELF specifications make a differnce between file size and memory + size of the segment. If the memory size is larger than the file + file, the remainder should be cleared with zeros. */ + if (php->p_memsz > php->p_filesz) + bzero(*dest + php->p_filesz, php->p_memsz - php->p_filesz); AVR_LOG(NULL, LOG_DEBUG, "Loaded %d bytes at %x\n", php->p_filesz, php->p_vaddr); return 0; @@ -299,15 +312,7 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) static int elf_handle_segment(int fd, Elf32_Phdr *php, uint8_t **dest, const char *name) { - if (*dest) { - AVR_LOG(NULL, LOG_ERROR, - "Unexpected extra %s data: %d bytes at %x.\n", - name, php->p_filesz, php->p_vaddr); - return -1; - } else { - elf_copy_segment(fd, php, dest); - return 0; - } + return elf_copy_segment(fd, php, dest); } /* The structure *firmware must be pre-initialised to zero, then optionally @@ -363,6 +368,8 @@ elf_read_firmware( return -1; } + firmware->flashbase = UINT_MAX; + for (i = 0; i < (int)ph_count; ++i, ++php) { #if 0 printf("Header %d type %d addr %x/%x size %d/%d flags %x\n", @@ -376,8 +383,8 @@ elf_read_firmware( if (elf_handle_segment(fd, php, &firmware->flash, "Flash")) continue; - firmware->flashsize = php->p_filesz; - firmware->flashbase = php->p_vaddr; + if (php->p_vaddrflashbase) + firmware->flashbase = php->p_vaddr; } else if (php->p_vaddr < 0x810000) { /* Data space. If there are initialised variables, treat * them as extra initialised flash. The C startup function @@ -421,6 +428,8 @@ elf_read_firmware( } } + firmware->flashsize = malloc_usable_size(firmware->flash); + /* Scan the section table for .mmcu magic and symbols. */ while ((scn = elf_nextscn(elf, scn)) != NULL) { From 12f64a97c78e8e819d9a4bcfb376f58e99faef35 Mon Sep 17 00:00:00 2001 From: dmantione Date: Fri, 21 Oct 2022 22:36:58 +0200 Subject: [PATCH 02/10] - Remove elf_handle_segment() --- simavr/sim/sim_elf.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 5a96418ee..9942e0776 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -309,12 +309,6 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) return 0; } -static int -elf_handle_segment(int fd, Elf32_Phdr *php, uint8_t **dest, const char *name) -{ - return elf_copy_segment(fd, php, dest); -} - /* The structure *firmware must be pre-initialised to zero, then optionally * tracing and VCD information may be added. */ @@ -381,7 +375,7 @@ elf_read_firmware( if (php->p_vaddr < 0x800000) { /* Explicit flash section. Load it. */ - if (elf_handle_segment(fd, php, &firmware->flash, "Flash")) + if (elf_copy_segment(fd, php, &firmware->flash)) continue; if (php->p_vaddrflashbase) firmware->flashbase = php->p_vaddr; @@ -394,8 +388,8 @@ elf_read_firmware( if (firmware->flash) { uint8_t *where; - firmware->flash = realloc(firmware->flash, - firmware->flashsize + php->p_filesz); + firmware->flash = + realloc(firmware->flash,firmware->flashsize + php->p_filesz); if (!firmware->flash) return -1; where = firmware->flash + firmware->flashsize; @@ -412,19 +406,19 @@ elf_read_firmware( } else if (php->p_vaddr < 0x820000) { /* EEPROM. */ - if (elf_handle_segment(fd, php, &firmware->eeprom, "EEPROM")) + if (elf_copy_segment(fd, php, &firmware->eeprom)) continue; firmware->eesize = php->p_filesz; } else if (php->p_vaddr < 0x830000) { /* Fuses. */ - if (elf_handle_segment(fd, php, &firmware->fuse, "Fuses")) + if (elf_copy_segment(fd, php, &firmware->fuse)) continue; firmware->fusesize = php->p_filesz; } else if (php->p_vaddr < 0x840000) { /* Lock bits. */ - elf_handle_segment(fd, php, &firmware->lockbits, "Lock bits"); + elf_copy_segment(fd, php, &firmware->lockbits); } } From f87cd95173213ef5f6e5ec9a5d4306e1aae78e5e Mon Sep 17 00:00:00 2001 From: dmantione Date: Fri, 21 Oct 2022 23:11:17 +0200 Subject: [PATCH 03/10] - Remove elf_firmware_t.flashbase --- simavr/sim/run_avr.c | 4 ---- simavr/sim/sim_elf.c | 12 ++---------- simavr/sim/sim_elf.h | 1 - simavr/sim/sim_hex.c | 25 ++++++++++++------------- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/simavr/sim/run_avr.c b/simavr/sim/run_avr.c index dfa6fcecb..495128965 100644 --- a/simavr/sim/run_avr.c +++ b/simavr/sim/run_avr.c @@ -251,10 +251,6 @@ main( #endif //CONFIG_SIMAVR_TRACE avr_load_firmware(avr, &f); - if (f.flashbase) { - printf("Attempted to load a bootloader at %04x\n", f.flashbase); - avr->pc = f.flashbase; - } for (int ti = 0; ti < trace_vectors_count; ti++) { for (int vi = 0; vi < avr->interrupts.vector_count; vi++) if (avr->interrupts.vector[vi]->vector == trace_vectors[ti]) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 9942e0776..c0db835c6 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -76,9 +76,8 @@ avr_load_firmware( #endif avr_loadcode(avr, firmware->flash, - firmware->flashsize, firmware->flashbase); - avr->codeend = firmware->flashsize + - firmware->flashbase - firmware->datasize; + firmware->flashsize, 0); + avr->codeend = firmware->flashsize - firmware->datasize; if (firmware->eeprom && firmware->eesize) { avr_eeprom_desc_t d = { @@ -362,8 +361,6 @@ elf_read_firmware( return -1; } - firmware->flashbase = UINT_MAX; - for (i = 0; i < (int)ph_count; ++i, ++php) { #if 0 printf("Header %d type %d addr %x/%x size %d/%d flags %x\n", @@ -377,8 +374,6 @@ elf_read_firmware( if (elf_copy_segment(fd, php, &firmware->flash)) continue; - if (php->p_vaddrflashbase) - firmware->flashbase = php->p_vaddr; } else if (php->p_vaddr < 0x810000) { /* Data space. If there are initialised variables, treat * them as extra initialised flash. The C startup function @@ -466,9 +461,6 @@ elf_read_firmware( ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) { const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name); - // if its a bootloader, this symbol will be the entry point we need - if (!strcmp(name, "__vectors")) - firmware->flashbase = sym.st_value; avr_symbol_t * s = malloc(sizeof(avr_symbol_t) + strlen(name) + 1); strcpy((char*)s->symbol, name); s->addr = sym.st_value; diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h index 37d61d703..3e335531a 100644 --- a/simavr/sim/sim_elf.h +++ b/simavr/sim/sim_elf.h @@ -64,7 +64,6 @@ typedef struct elf_firmware_t { uint16_t command_register_addr; uint16_t console_register_addr; - uint32_t flashbase; // base address uint8_t * flash; uint32_t flashsize; uint32_t datasize; diff --git a/simavr/sim/sim_hex.c b/simavr/sim/sim_hex.c index fea67c48a..8d2ad202a 100644 --- a/simavr/sim/sim_hex.c +++ b/simavr/sim/sim_hex.c @@ -220,19 +220,18 @@ sim_setup_firmware(const char * filename, uint32_t loadBase, for (int ci = 0; ci < cnt; ci++) { if (chunk[ci].baseaddr < (1*1024*1024)) { - if (fp->flash) { - printf("Ignoring chunk %d, " - "possible flash redefinition %08x, %d\n", - ci, chunk[ci].baseaddr, chunk[ci].size); - free(chunk[ci].data); - chunk[ci].data = NULL; - continue; - } - fp->flash = chunk[ci].data; - fp->flashsize = chunk[ci].size; - fp->flashbase = chunk[ci].baseaddr; - printf("Load HEX flash %08x, %d at %08x\n", - fp->flashbase, fp->flashsize, fp->flashbase); + uint32_t segment_end = chunk[ci].baseaddr + chunk[ci].size; + if (fp->flashsizeflash==NULL (i.o.w. no memory allocated yet) */ + realloc(fp->flash,segment_end); + memcpy(fp->flash + chunk[ci].baseaddr, chunk[ci].data, chunk[ci].size); + free(chunk[ci].data); + chunk[ci].data = NULL; + fp->flashsize = segment_end; + printf("Load HEX flash addr=%08x sz=%d\n", + chunk[ci].baseaddr, fp->flashsize); } else if (chunk[ci].baseaddr >= AVR_SEGMENT_OFFSET_EEPROM || (chunk[ci].baseaddr + loadBase) >= AVR_SEGMENT_OFFSET_EEPROM) { From 6fd3036ed7d21ef420b50c78df7b8c2147ed786d Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 12:24:50 +0200 Subject: [PATCH 04/10] * Proper use of realloc. --- simavr/sim/sim_hex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simavr/sim/sim_hex.c b/simavr/sim/sim_hex.c index 8d2ad202a..155109743 100644 --- a/simavr/sim/sim_hex.c +++ b/simavr/sim/sim_hex.c @@ -225,7 +225,7 @@ sim_setup_firmware(const char * filename, uint32_t loadBase, /* Allocate enough memory to load the segment. Note that realloc does the right thing in case fp->flash==NULL (i.o.w. no memory allocated yet) */ - realloc(fp->flash,segment_end); + fp->flash = realloc(fp->flash,segment_end); memcpy(fp->flash + chunk[ci].baseaddr, chunk[ci].data, chunk[ci].size); free(chunk[ci].data); chunk[ci].data = NULL; From 9a806da16a83b8b0c115212246d50f52bfba7407 Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 12:25:50 +0200 Subject: [PATCH 05/10] + Add buffer size parameter to elf_copy_segment * Use paddr (load address) rather than vaddr (runtime address) - Remove special handling of initialized data sections --- simavr/sim/sim_elf.c | 65 ++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index c0db835c6..ee2734898 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -274,23 +274,24 @@ elf_parse_mmcu_section( } static int -elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) +elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **buffer, uint32_t *bufsize) { int rv; Elf32_Addr segment_end; /* Allocate enough memory to load the segment. Note that both malloc_usable_size and realloc do the right thing in - case *dest==NULL (i.o.w. no memory allocated yet) */ - segment_end = php->p_vaddr + php->p_memsz; - if (malloc_usable_size(*dest) < segment_end) { - *dest = realloc(*dest, segment_end); + case *buffer==NULL (i.o.w. no memory allocated yet) */ + segment_end = php->p_paddr + php->p_memsz; + if (*bufsize < segment_end) { + *buffer = realloc(*buffer, segment_end); + *bufsize = segment_end; } - if (!*dest) + if (!*buffer) return -1; lseek(fd, php->p_offset, SEEK_SET); - rv = read(fd, *dest + php->p_vaddr, php->p_filesz); + rv = read(fd, *buffer + php->p_paddr, php->p_filesz); if (rv != php->p_filesz) { AVR_LOG(NULL, LOG_ERROR, "Got %d when reading %d bytes for %x at offset %d " @@ -302,9 +303,9 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) size of the segment. If the memory size is larger than the file file, the remainder should be cleared with zeros. */ if (php->p_memsz > php->p_filesz) - bzero(*dest + php->p_filesz, php->p_memsz - php->p_filesz); + bzero(*buffer + php->p_filesz, php->p_memsz - php->p_filesz); AVR_LOG(NULL, LOG_DEBUG, "Loaded %d bytes at %x\n", - php->p_filesz, php->p_vaddr); + php->p_filesz, php->p_paddr); return 0; } @@ -369,51 +370,21 @@ elf_read_firmware( #endif if (php->p_type != PT_LOAD || php->p_filesz == 0) continue; - if (php->p_vaddr < 0x800000) { + if (php->p_paddr < 0x800000) { /* Explicit flash section. Load it. */ - - if (elf_copy_segment(fd, php, &firmware->flash)) + if (elf_copy_segment(fd, php, &firmware->flash, &firmware->flashsize)) continue; - } else if (php->p_vaddr < 0x810000) { - /* Data space. If there are initialised variables, treat - * them as extra initialised flash. The C startup function - * understands that and will copy them to RAM. - */ - - if (firmware->flash) { - uint8_t *where; - - firmware->flash = - realloc(firmware->flash,firmware->flashsize + php->p_filesz); - if (!firmware->flash) - return -1; - where = firmware->flash + firmware->flashsize; - elf_copy_segment(fd, php, &where); - firmware->flashsize += php->p_filesz; - } else { - /* If this ever happens, add a second pass. */ - - AVR_LOG(NULL, LOG_ERROR, - "Initialialised data but no flash (%d bytes at %x)!\n", - php->p_filesz, php->p_vaddr); - return -1; - } - } else if (php->p_vaddr < 0x820000) { + } else if (php->p_paddr < 0x820000) { /* EEPROM. */ - - if (elf_copy_segment(fd, php, &firmware->eeprom)) + if (elf_copy_segment(fd, php, &firmware->eeprom, &firmware->eesize)) continue; - firmware->eesize = php->p_filesz; - } else if (php->p_vaddr < 0x830000) { + } else if (php->p_paddr < 0x830000) { /* Fuses. */ - - if (elf_copy_segment(fd, php, &firmware->fuse)) + if (elf_copy_segment(fd, php, &firmware->fuse, &firmware->fusesize)) continue; - firmware->fusesize = php->p_filesz; - } else if (php->p_vaddr < 0x840000) { + } else if (php->p_paddr < 0x840000) { /* Lock bits. */ - - elf_copy_segment(fd, php, &firmware->lockbits); + elf_copy_segment(fd, php, &firmware->lockbits, &firmware->fusesize); } } From 16ecff433be0dd46e06ba2798379d5ff051fecd1 Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 12:28:54 +0200 Subject: [PATCH 06/10] - Remove last invokation of malloc_usable_size. --- simavr/sim/sim_elf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index ee2734898..e07c8bcde 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -388,8 +388,6 @@ elf_read_firmware( } } - firmware->flashsize = malloc_usable_size(firmware->flash); - /* Scan the section table for .mmcu magic and symbols. */ while ((scn = elf_nextscn(elf, scn)) != NULL) { From 24794b163567493f65a52502d908d5ead14eb5ce Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 12:44:18 +0200 Subject: [PATCH 07/10] * Use memset instead of bzero --- simavr/sim/sim_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index e07c8bcde..6cd9b518c 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -303,7 +303,7 @@ elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **buffer, uint32_t *bufsize) size of the segment. If the memory size is larger than the file file, the remainder should be cleared with zeros. */ if (php->p_memsz > php->p_filesz) - bzero(*buffer + php->p_filesz, php->p_memsz - php->p_filesz); + memset(*buffer + php->p_filesz, 0, php->p_memsz - php->p_filesz); AVR_LOG(NULL, LOG_DEBUG, "Loaded %d bytes at %x\n", php->p_filesz, php->p_paddr); return 0; From a47328e08ec737f98091cdaf6f4568d3c624924e Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 15:09:27 +0200 Subject: [PATCH 08/10] * Handle SRAM addresses again, as error condition. --- simavr/sim/sim_elf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 6cd9b518c..250a51901 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -374,6 +374,9 @@ elf_read_firmware( /* Explicit flash section. Load it. */ if (elf_copy_segment(fd, php, &firmware->flash, &firmware->flashsize)) continue; + } else if (php->p_paddr < 0x810000) { + AVR_LOG(NULL, LOG_ERROR, "ELF file attempts to load data into AVR SRAM!\n"); + return -1; } else if (php->p_paddr < 0x820000) { /* EEPROM. */ if (elf_copy_segment(fd, php, &firmware->eeprom, &firmware->eesize)) From 0a5cc2bcce60346b809fa6a2fa13a77da22a34a3 Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 15:43:24 +0200 Subject: [PATCH 09/10] + Introduce a locksize field. --- simavr/sim/sim_elf.c | 2 +- simavr/sim/sim_elf.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index 250a51901..f2e01e94d 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -387,7 +387,7 @@ elf_read_firmware( continue; } else if (php->p_paddr < 0x840000) { /* Lock bits. */ - elf_copy_segment(fd, php, &firmware->lockbits, &firmware->fusesize); + elf_copy_segment(fd, php, &firmware->lockbits, &firmware->locksize); } } diff --git a/simavr/sim/sim_elf.h b/simavr/sim/sim_elf.h index 3e335531a..da1d79c49 100644 --- a/simavr/sim/sim_elf.h +++ b/simavr/sim/sim_elf.h @@ -74,6 +74,7 @@ typedef struct elf_firmware_t { uint8_t * fuse; uint32_t fusesize; uint8_t * lockbits; + uint32_t locksize; #if ELF_SYMBOLS avr_symbol_t ** symbol; From 348815362b0bf1e655fa0baeb26a1dffec32f069 Mon Sep 17 00:00:00 2001 From: dmantione Date: Sat, 22 Oct 2022 15:46:57 +0200 Subject: [PATCH 10/10] - malloc.h and limits.h no longer needed for current patch --- simavr/sim/sim_elf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/simavr/sim/sim_elf.c b/simavr/sim/sim_elf.c index f2e01e94d..dd42f24e9 100644 --- a/simavr/sim/sim_elf.c +++ b/simavr/sim/sim_elf.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include