summaryrefslogtreecommitdiffstats
path: root/firmware/load_code.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/load_code.c')
-rw-r--r--firmware/load_code.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/firmware/load_code.c b/firmware/load_code.c
index 75bac8b2ac..5b5307e622 100644
--- a/firmware/load_code.c
+++ b/firmware/load_code.c
@@ -26,37 +26,77 @@
#include "load_code.h"
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+
/* load binary blob from disk to memory, returning a handle */
-void * lc_open(const char *filename, char *buf, size_t buf_size)
+void * lc_open(const char *filename, unsigned char *buf, size_t buf_size)
{
int fd = open(filename, O_RDONLY);
ssize_t read_size;
+ struct lc_header hdr;
+ unsigned char *buf_end = buf+buf_size;
+ off_t copy_size;
if (fd < 0)
{
DEBUGF("Could not open file");
- return NULL;
+ goto error;
}
#if NUM_CORES > 1
/* Make sure COP cache is flushed and invalidated before loading */
{
int my_core = switch_core(CURRENT_CORE ^ 1);
- cpucache_invalidate();
+ cpucache_commit_discard();
switch_core(my_core);
}
#endif
- read_size = read(fd, buf, buf_size);
+ /* read the header to obtain the load address */
+ read_size = read(fd, &hdr, sizeof(hdr));
+
+ if (read_size < 0)
+ {
+ DEBUGF("Could not read from file");
+ goto error_fd;
+ }
+
+ /* hdr.end_addr points to the end of the bss section,
+ * but there might be idata/icode behind that so the bytes to copy
+ * can be larger */
+ copy_size = MAX(filesize(fd), hdr.end_addr - hdr.load_addr);
+
+ if (hdr.load_addr < buf || (hdr.load_addr+copy_size) > buf_end)
+ {
+ DEBUGF("Binary doesn't fit into memory");
+ goto error_fd;
+ }
+
+ /* go back to beginning to load the whole thing (incl. header) */
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ {
+ DEBUGF("lseek failed");
+ goto error_fd;
+ }
+
+ /* the header has the addresses where the code is linked at */
+ read_size = read(fd, hdr.load_addr, copy_size);
close(fd);
- cpucache_invalidate();
if (read_size < 0)
{
DEBUGF("Could not read from file");
- return NULL;
+ goto error;
}
- return buf;
+
+ /* commit dcache and discard icache */
+ cpucache_commit_discard();
+ /* return a pointer the header, reused by lc_get_header() */
+ return hdr.load_addr;
+
+error_fd:
+ close(fd);
+error:
+ return NULL;
}
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
@@ -85,12 +125,11 @@ static inline char *_dlerror(void)
#include "rbpaths.h"
#include "general.h"
-void * _lc_open(const _lc_open_char *filename, char *buf, size_t buf_size)
+void * _lc_open(const _lc_open_char *filename, unsigned char *buf, size_t buf_size)
{
(void)buf;
(void)buf_size;
- void* dl_handle = dlopen(filename, RTLD_NOW);
- return dl_handle;
+ return dlopen(filename, RTLD_NOW);
}
void *lc_open_from_mem(void *addr, size_t blob_size)